c语言结构交换结点指针域,数据结构学习笔记——线性表之单链表(c语言实现)...

本文详细介绍了单链表的概念、存储结构,以及如何用C语言实现单链表的创建、在指定位置插入和删除元素、修改数据、查找操作,并通过冒泡排序进行链表排序。此外,还分析了单链表相对于顺序表的优势,适合于元素数量不确定或频繁进行插入和删除的情况。
摘要由CSDN通过智能技术生成

1.概念

链式存储结构:是指把数据元素存放在任意内存未被占用的存储单元里,这组存储单元可以是连续的,也可以是不连续的。

大概就是这样:

b56c71689148a17aa1545c0eb4f452c0.png

因此,为了表示每个数据元素a1,与其直接后继数据元素 a2 之间的逻辑关系,对数据元素a来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。

对此有如下几个概念:

数据域

指针域

指针(链)

头指针

存储数据元素信息的域

存储直接后继位置的域

指针域中存储的信息

指向第一个结点的指针,具有标识作用常冠以链表名字,是链表的必要元素

结点

链表

单链表

头结点

数据域与指针域的结合

n 个结点按一定逻辑次序的链结

链表的每个结点中只包含一个指针域

放在第一元素结点之前,数据域一般无意义,非必要

下图即为一个单链表:

ea820fa00dfebbb91a2612bdd7932eae.png

2.实现

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

(1)建立结点结构

19d1ad4b5d5e9ee3898831dd794e3ec1.png

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);

}

}

结果演示:

4c20e1c5d01c7701b9cf6cdf333323be.png

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

2dd8000e32390f15597b28916dd0ec01.png

示例代码:

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)||i

{

printf("error!节点不存在!\n");

return;

}

while (j

{

p=p->next;

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个结点处插入:

尾插:

7b3e76f212e4675f20c60084dc87f11d.png

头插:

f540cdb49e64767591e38488f8fe4545.png

第3个结点处:

60ecd0c0ccc3072acd4bc1b854be7363.png

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

f431f337487311e0902dc66efe8ec41c.png

示例代码:

Status SListDelete(SlNode *L)

{

int j=1;

int i;

SlNode *p=L;

SlNode *q;

printf("请输入Nob:");

scanf("%d",&i);

if (i>(L->length)||i

{

printf("error!节点不存在!\n");

return 0;

}

while (j

{

p=p->next;

j++;

}

//删除q节点

q=p->next;

p->next=q->next;

free(q);

--(L->length);

return 1;

}

结果演示:

删除第三个结点

01ab34a068a105704bebd70f6c50b7ee.png

(5)改:更改数据

7f71b30a7c013cad77ae210ef5e0d858.png

示例代码:

Status SListUpdate(SlNode *L)

{

int j=1;

int i;

SlNode *p=L->next;

printf("请输入Nob:");

scanf("%d",&i);

if (i>(L->length)||i

{

printf("error!节点不存在!\n");

return 0;

}

while (j

{

p=p->next;

j++;

}

printf("新name:");

scanf("%s",p->name);

printf("新number:");

scanf("%d",p->number);

return 1;

}

结果演示:

更改第三个结点数据

136b3141f9016983bca7baaa320fdb2a.png

(6)查:查找数据

dca1510590cc7b29d9d723d240f34ba1.png

本例程中若要查找字符串类型的数据,在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");

}

}

结果演示:

按序号查找:

aa5aa19ebe6e36d085db741890c9a297.png

按name查找:

f9f0548971045886c5fc5af701f55e4f.png

按number查找:

da84a99620dabc3bba53dcd8e55fb0f8.png

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

排序方法多种多样,有两篇博文对各种排序方法都有不错的介绍和实现:

https://www..com/eniac12/p/5329396.html#s1

https://www..com/eniac12/p/5332117.html

此处选用冒泡排序,算法示意图如下:

4692e9719fc6eea2dd31dfc375a7a1e1.gif

在单链表中使用冒泡排序关键在于相邻两个结点的交换:

7d7145f3a15d2e47fa04caa6625ebaa4.png

交换后p往后退一格:

fb5377cbf353d267e974d6b6684a93a2.png

示例代码:

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);//打印表单

}

结果演示:

6ccdc0602dd6813844824dece6726932.png

(8)其他

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

3.优劣势分析

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值