算法2---链表1---链表简单的实现

1 链表的基本知识

1.1 基本定义及优缺点

链表中各个对象按照顺序排列,注意到和数组的区别,数组的线性顺序是由数组下标决定的,但是链表的顺序是由各个对象里的指针决定的。

链表包含两个方面:1 数据部分,保存的是节点的实际数据;2 地址部分,保存的是下一个节点的地址(单链表)。

那么链表的优缺点

优点:方便理解,操作方便;

缺点:1在插入和删除操作的时候,往往需要移动大量的数据;2如果表比较大,有时候会难以分配足够的连续空间,导致内存分配失败,而无法存储;

1.2 分类

单链表:每个节点中只包含一个指针;

双向链表:每个节点包含两个指针,一个指向下一个节点,一个指向上一个节点;

单循环链表:在单链表中,将终端节点的指针域NULL改为指向表头节点或开始节点的就构成单循环链表。

双循环链表:首节点的指向上一个节点的指针指向链表尾节点,尾节点指向下一个节点的指针指向表头及诶到哪构成双循环链表;

2 链表的实现C语言版本

2.1 简单的实现

首先我们不考虑各种适应性,首先就固定data的形式;

包含两个文件夹list_simple.h,list_simple.c

list_simple.h

#ifndef _list_simple_H

typedef struct
{
    char key[10];
    char name[20];
    int age;
}Data;

typedef struct Node
{
    Data nodeData;
    struct Node *nextNode;
}CLType;

CLType *CLAddEnd (CLType *head,Data nodeData);
CLType *CLAddFirst(CLType *head,Data nodeData);
CLType *CLFindNode(CLType *head,char *key);
CLType *CLinsertNode(CLType *head,char *findkey,Data nodeData);
int CLDeleteNode(CLType *head,char *key);
int CLLength(CLType *head);
void CLAllNode(CLType *head);

#endif

/*=======================================*/
//追加结点;
CLType *CLAddEnd (CLType *head,Data nodeData)
{
    CLType *node,*htemp;
    if (!(node=(CLType)malloc(sizeof(CLType))))//分配空间
    {
        printf("内存分配失败!\n");
        return NULL;
    }
    else
    {
        node->nodeData=nodeData;//保存数据
        node->nextNode=NULL//设置结点指针为空,即为表尾;
        if (head==NULL)
        {
            head=node;
            return head;
        }
        htemp=head;
        while(htemp->nextNode!=NULL)
        {
            htemp=htemp->nextNode;
        }
        htemp->nextNode=node;
        return head;
    }
}

/*=======================================*/
//插入头结点
CLType *CLAddFirst(CLType *head,Data nodeData)
{
    CLType *node;
    if (!(node=(CLType)malloc(sizeof(CLType))))
    {
        printf("内存分配失败\n");
        return NULL;
    }
    else
    {
        node->nodeData=nodeData;
        node->nextNode=head;
        head=node;
        return head;
    }
}

/*=======================================*/
//查找结点
CLType *CLFindNode(CLType *head,char *key)
{
    CLType *htemp;
    htemp=head;
    while(htemp)
    {
        if (stcmp(htemp->nodeDate.key,key)==0)
        {
            return htemp;
        }
        htemp=htemp->nextNode;
    }
    return NULL;
}

/*=======================================*/
CLType *CLinsertNode(CLType *head,char *findkey,Data nodeData)
{
    CLType *node,*nodetemp;
    if (!(node=(CLType)malloc(sizeof(CLType))))
    {
        printf("内存分配失败!\n");
        return NULL;
    }
    node->nodeData=nodeData;
    nodetemp=CLFindNode(head,findkey);
    if (nodetemp)
    {
        node->nextNode=nodetemp->nextNode;
        nodetemp->nextNode=node;
    }
    else
    {
        printf("未找到争取的的插入位置\n");
        free(node);
    }
    return head;
}
/*=======================================*/
//delete the node;

int CLDeleteNode(CLType *head,char *key)
{
    CLType *node,*htemp;
    htemp=head;
    node=head;
    while(htemp)
    {
        if (strcmp(htemp->nodeData.key,key)==0)
        {
            node->nextNode=htemp->nextNode;
            free(htemp);
            return 1;
        }
        else
        {
            node=htemp;
            htemp=htemp->nextNode;
        }
    }
    return 0;
}

/*=======================================*/
//计算链表的长度
int CLLength(CLType *head)
{
    CLType *htemp;
    int len=0;
    htemp=head;
    while(htemp)
    {
        len++;
        htemp=htemp->nextNode;
    }
    return len;
}

/*=======================================*/
//显示所有的结点
void CLAllNode(CLType *head)
{
    CLType *htemp;
    Data nodeData;
    htemp=head;
    printf("当前链表共有%d个结点,链表的所有数据如下:\n", CLLength(head));
    while(htemp)
    {
        nodeData=htemp->nodeData;
        printf("node:(%s,%s,%d)\n",nodeData.key,nodeData.name,nodeData.age );
        htemp=htemp->nextNode;
    }
}

list_simple.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "list_simple.h"

void main()
{
    CLType *node,*head=NULL;
    Data nodeData;
    char key[10];
    char findkey[10];
    printf("链表测试,输入链表中的数据,输入格式为:关键字 姓名 年龄 \n");
    do
    {
        fflush(stdin);
        scanf("%s",nodeData.key);
        if (strcmp(nodeData.key,"0")==0)
        {
            break;//输入0,退出
        }
        else
        {
            scanf("%s%d",nodeData.name,&nodeData.age);
            head=CLAddEnd(head,nodeData);
        }
    }while(1);
    CLAllNode(head);

    printf("演示插入结点,输入插入位置的关键字:\n");
    scanf("%s",&findkey);
    printf("输入插入结点的数据(关键字 姓名 年龄)\n");
    scanf("%s%s%d",nodeData.key,nodeData.name,&nodeData.age);
    head=CLInsertNode(head,findkey,nodeData);
    CLAllNode(head);

    printf("演示删除结点,输入要删除的关键字:\n");
    fflush(stdin);
    scanf("%s",key);
    CLDeleteNode(head,key);
    CLAllNode(head);

    printf("演示在链表中查找,出入要查找的关键字:\n");
    fflush(stdin);
    scanf("%s",key);
    node=CLFindNode(head,key);
    if(node)
    {
        nodeData=node->nodeData;
        printf("关键字对应的结点为(%s%s%d)\n",key,nodeData.key,nodeData.name );
    }
    else
    {
        printf("在链表中没有找到你对应的结点\n");
    }

}

代码都已经编译通过!可以直接用

后面我们给出一个任意链表中存储任意类型的数据的实现方法,尽请期待:算法2---链表2---链表任意存储的实现

时间: 2024-11-06 22:30:02

算法2---链表1---链表简单的实现的相关文章

cc150:实现一个算法来删除单链表中间的一个结点,只给出指向那个结点的指针

实现一个算法来删除单链表中间的一个结点,只给出指向那个结点的指针. 例子: 输入:指向链表a->b->c->d->e中结点c的指针 结果:不需要返回什么,得到一个新链表:a->b->d->e 解答 这个问题的关键是你只有一个指向要删除结点的指针,如果直接删除它,这条链表就断了. 但你又没办法得到该结点之前结点的指针,是的,它连头结点也不提供.在这种情况下, 你只能另觅他径.重新审视一下这个问题,我们只能获得从c结点开始后的指针, 如果让你删除c结点后的某个结点,那

一步一步写算法(之单向链表)

原文:一步一步写算法(之单向链表) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 有的时候,处于内存中的数据并不是连续的.那么这时候,我们就需要在数据结构中添加一个属性,这个属性会记录下面一个数据的地址.有了这个地址之后,所有的数据就像一条链子一样串起来了,那么这个地址属性就起到了穿线连结的作用. 相比较普通的线性结构,链表结构的优势是什么呢?我们可以总结一下: (1)单个节点创建非常方便,普通的线性内存通常在创建的时候就需要设定数据的

cc150:实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针

实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针. 样例: 输入:指向链表a->b->c->d->e中结点c的指针 结果:不须要返回什么,得到一个新链表:a->b->d->e 解答 这个问题的关键是你仅仅有一个指向要删除结点的指针,假设直接删除它,这条链表就断了. 但你又没办法得到该结点之前结点的指针,是的,它连头结点也不提供.在这样的情况下, 你仅仅能另觅他径.又一次审视一下这个问题,我们仅仅能获得从c结点開始后的指针, 假设让你删除c结点后的

009实现一个算法来删除单链表中的一个结点,只给出指向那个结点的指针(keep it up)

呵呵,这个题不能直接删除已知的结点,因为是单链表,不知道前驱,只知道 后继结点,直接删除会使链表断开.不过我们可以删除已知结点的后继结点, 把后继结点的值赋值给已知结点. #include <iostream> struct Node { int data; Node* next; }; bool removeNode(Node* vNode) { if (vNode == NULL || vNode->next == NULL) return false; Node* pNext =

实现一个算法从一个单链表中返回倒数第n个元素(keep it up)

我们维护两个指针, 它们之间的距离为n.然后,我将这两个指针同步地在这个单链表上移动,保持它们的距离 为n不变.那么, 当第二个指针指到空时,第一个指针即为所求. #include <iostream> struct Node { int data; Node* next; }; void initList(Node* vNode) { for (int i=0; i < 20; ++i) { Node* TempNode = new Node; TempNode->data =

关于链表的一些简单操作

终于上黄金了.. 然后就是一波2连败... 最近 完全不想做题啊  一做题 就想碎觉啊 郁闷死了 根据书本 写了点关于单向链表的简单操作 可能还存在点小bug---先放它一马吧 以后可能再进行补充关于它的操作 毕竟还有好多 先慢慢找回敲键盘打代码的感觉 厌 1 /* 2 线性表之单向链表的一些常见操作 3 */ 4 #include <iostream> 5 using namespace std; 6 7 typedef int ElemType; 8 typedef struct LNod

数据结构之自建算法库——循环双链表

本文针对数据结构基础系列网络课程(2):线性表中第13课时循环链表. 按照"0207将算法变程序"[视频]部分建议的方法,建设自己的专业基础设施算法库. 双链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:cdlinklist.h,包含定义双链表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef CDLINKLIST_H_INCLUDED #define CDLINKLIST_H_INCLUDED //循环双链表基本运算函数 typedef int E

数据结构之自建算法库——循环单链表

本文针对数据结构基础系列网络课程(2):线性表中第13课时双链表. 按照"0207将算法变程序"[视频]部分建议的方法,建设自己的专业基础设施算法库. 双链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:clinklist.h,包含定义双链表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef CLINKLIST_H_INCLUDED #define CLINKLIST_H_INCLUDED //循环单链表基本运算函数 typedef int ElemT

算法题:求链表倒数第K个结点

说明:本文仅供学习交流,转载请标明出处,欢迎转载!  题目:给出一个单链表,返回倒数第K个结点,最后一个结点为倒数第1个. <剑指offer>上面给的解法是设置两个指针,这里记为p1.p2,先让p2走(k-1)步,然后p1.p2同时走,当p2走到最后一个结点时,p1所指向的结点就是倒数第k个结点. 我觉得按照这样的逻辑写代码反而更容易出错,因为我们需要把我两件重要的问题:(1).p2先走(k-1)步:(2)循环结束的条件是p2到达最后一个结点,即p2->next==NULL.显然这样不太

链表栈的简单实现

今天实现了链表栈的简单实现,贴出来以后可以看一看.链表栈就是用链表来实现栈的一些操作. LinkStack.h #ifndef LINKSTACK_H_ #define LINKSTACK_H_ #include <iostream> using std::cout; using std::endl; using std::ostream; template <typename T> struct Node { T data; Node<T> *next; Node()