数据结构学习笔记——线性表之单链表(c语言实现)

1.概念

链式存储结构:是指把数据元素存放在任意内存未被占用的存储单元里,这组存储单元可以是连续的,也可以是不连续的。
大概就是这样:
数据结构学习笔记——线性表之单链表(c语言实现)_第1张图片
因此,为了表示每个数据元素a1,与其直接后继数据元素 a2 之间的逻辑关系,对数据元素a来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。
对此有如下几个概念:

数据域 指针域 指针(链) 头指针
存储数据元素信息的域 存储直接后继位置的域 指针域中存储的信息 指向第一个结点的指针,具有标识作用常冠以链表名字,是链表的必要元素
结点 链表 单链表 头结点
数据域与指针域的结合 n 个结点按一定逻辑次序的链结 链表的每个结点中只包含一个指针域 放在第一元素结点之前,数据域一般无意义,非必要

下图即为一个单链表:
数据结构学习笔记——线性表之单链表(c语言实现)_第2张图片

2.实现

完整代码下载地址:https://download.csdn.net/download/luotuoxiansheng/10756421

(1)建立结点结构

数据结构学习笔记——线性表之单链表(c语言实现)_第3张图片

typedef struct SlNode
{
    ElemType1 name[DATA1LENGTH];  //创建数组存储空间
    ElemType2 number[DATA2LENGTH];
    ElemType2 length;             //标识表长
    struct SlNode *next;          //创建指向结点的指针
}SlNode,*LinkList;
(2)创建表单

创建结点数据并利用尾插法依次插入链表,形成初始的单链表

示例代码:

void CreateList(SlNode *L)
 {
     SlNode *p,*newnode;
     L->length=0;
     p=L;
     char flag='y';
    puts("创建表单:");
	while(flag=='Y'||flag=='y'){
        newnode=(LinkList)malloc(sizeof(SlNode));
		printf("name:");
		scanf("%s",newnode->name);
		printf("number:");
		scanf("%d",newnode->number);

        //节点插入(尾部)
		newnode->next=NULL;
        p->next=newnode;
        p=newnode;
        L->length++;

		getchar();//等待输入完成后的回车键
		printf("继续输入?(y/n)");
		scanf("%c",&flag);
	}   
 }

结果演示:
数据结构学习笔记——线性表之单链表(c语言实现)_第4张图片

(3)增:在第i个位置插入数据

数据结构学习笔记——线性表之单链表(c语言实现)_第5张图片
示例代码:

void SListInsert(SlNode *L)
{
    int i;
    int j=1,n=1;
    SlNode *p,*newnode;
    p=L;
    printf("在第几个位置插入?请输入:");
    scanf("%d",&i);
    if (i>(L->length+1)||inext;
       j++;
    }
    
    //找到插入位置后创建结点数据
    newnode=(LinkList)malloc(sizeof(SlNode));
    printf("name: ");
    scanf("%s",newnode->name);
    printf("number: ");
    scanf("%d",newnode->number);
    
    //插入
    newnode->next=p->next;
    p->next=newnode;

    if(i==L->length+1)//如果是在尾部插入,则让newnode->next=NULL;
    newnode->next=NULL;

    L->length++;
}

结果演示:
可在任意位置插入结点。依次在尾部、头部、第i个结点处插入:
尾插:
数据结构学习笔记——线性表之单链表(c语言实现)_第6张图片
头插:
数据结构学习笔记——线性表之单链表(c语言实现)_第7张图片
第3个结点处:
数据结构学习笔记——线性表之单链表(c语言实现)_第8张图片

(4)删:删除第i个数据

数据结构学习笔记——线性表之单链表(c语言实现)_第9张图片
示例代码:

Status SListDelete(SlNode *L)
{
    int j=1;
    int i;
    SlNode *p=L;
    SlNode *q;
    printf("请输入Nob:");
    scanf("%d",&i);
    if (i>(L->length)||inext;
       j++;
    }
        //删除q节点
        q=p->next;
        p->next=q->next;
        free(q);
        --(L->length);
        return 1;
}

结果演示:
删除第三个结点
数据结构学习笔记——线性表之单链表(c语言实现)_第10张图片

(5)改:更改数据

数据结构学习笔记——线性表之单链表(c语言实现)_第11张图片
示例代码:

  Status SListUpdate(SlNode *L)
{
    int j=1;
    int i;
    SlNode *p=L->next;
    printf("请输入Nob:");
    scanf("%d",&i);
    if (i>(L->length)||inext;
       j++;
    }
        printf("新name:");
		scanf("%s",p->name);
		printf("新number:");
		scanf("%d",p->number);

        return 1;
}

结果演示:
更改第三个结点数据
数据结构学习笔记——线性表之单链表(c语言实现)_第12张图片

(6)查:查找数据

数据结构学习笔记——线性表之单链表(c语言实现)_第13张图片

本例程中若要查找字符串类型的数据,在c语言中应使用strcmp()函数去匹配查找,不能直接使用“==”匹配,笔者因为这个问题在这出现了很多错误。

示例代码:

SlNode *SListGet(SlNode *L)
{
    int n;
    ElemType2 Nob;
    int ch;
    SlNode *p;
    SlNode *input;
    SlNode *get;
    p=L->next;
    input=(LinkList)malloc(sizeof(SlNode));//创建结点用于存储输入数据
    printf("查找项(1.Nob/2.name/3.number):");
    scanf("%d",&ch);
    switch(ch)
    {
        case 1:{
                printf("请输入Nob:");
                scanf("%d",&Nob);
                n=1;
                  while(n<=L->length)
                {
                    if(Nob==n)
                        {
                           get=p;
                           return get;
                        }

                    p=p->next;
                    n++;
                }  
                 printf("没有此数据!\n");return 0;
        };break;

        case 2:{
                n=1;
                printf("请输入name:");
                scanf("%s",input->name);
                while(n<=L->length)
                {
                    if(!strcmp(p->name,input->name))//若两个字符串相等
                        {
                           get=p;
                           return get;//找到就返回
                        }
                    p=p->next;
                    n++;
                }
                 printf("没有此数据!\n");return 0;
        };break;

        case 3:{
                n=1;
                printf("请输入number:");
                scanf("%d",input->number);
                 while(n<=L->length)
                {
                    if(*p->number==*input->number)
                        {
                           get=p;
                           return get;//找到就返回
                        }
                    p=p->next;
                    n++;
                }
                 printf("没有此数据!\n");return 0;
        };break;
        default: printf("错误!没有这个选项!\n");
    }
}

结果演示:
按序号查找:
数据结构学习笔记——线性表之单链表(c语言实现)_第14张图片
按name查找:
数据结构学习笔记——线性表之单链表(c语言实现)_第15张图片
按number查找:
数据结构学习笔记——线性表之单链表(c语言实现)_第16张图片

(7)排序:对表单按照number升序重新排序(冒泡排序法)

排序方法多种多样,有两篇博文对各种排序方法都有不错的介绍和实现:
https://www.cnblogs.com/eniac12/p/5329396.html#s1
https://www.cnblogs.com/eniac12/p/5332117.html

此处选用冒泡排序,算法示意图如下:
数据结构学习笔记——线性表之单链表(c语言实现)_第17张图片

在单链表中使用冒泡排序关键在于相邻两个结点的交换:
数据结构学习笔记——线性表之单链表(c语言实现)_第18张图片
交换后p往后退一格:
数据结构学习笔记——线性表之单链表(c语言实现)_第19张图片
示例代码:

 void SListSort(SlNode *L)
{
    int i,j;
    SlNode *pre=L;
    SlNode *p=L->next;
    SlNode *tmp;

    for (i=0;ilength-1;i++)
    {
        pre=L;
        p=L->next;
        for (j=0;jlength-1-i;j++)
        {
            if (*(p->number)>*(p->next->number))
            {
                //交换节点
                pre->next=p->next; 
				p->next = p->next->next;
                pre->next->next=p;
                p=pre->next;//更新p的位置
            }
            //p再前进一个结点
            p=p->next; 
			pre=pre->next;
        }
    }
    PrintList(L);//打印表单
}

结果演示:
数据结构学习笔记——线性表之单链表(c语言实现)_第20张图片

(8)其他

表单打印和清空整表的内容不再详细写出,详见完整代码,下载地址:https://download.csdn.net/download/luotuoxiansheng/10756421

3.优劣势分析

比较顺序表,单链表更加灵活,且存储空间大小不确定。若需要频繁插入和删除时适合使用单链表,以及当线性表中的元素个数变化较大或者根本不知道有多大时宜采用单链表结构。

以上就是对单链表的学习和分享

你可能感兴趣的:(数据结构学习笔记)