数据结构与算法c语言链表,C+数据结构与算法之链表之单链表

1.单链表定义

每个节点包括一个数据域一个指针域,节点在内存中地址可以不连续,但是节点内部地址必然连续。

bVbmOkc?w=547&h=40

2.结构定义

typedef struct Lnode{

int data;

struct Lnode *next;

}Lnode,*LinkList;

3.单链表的创建

1)头插法

bVbmOld?w=477&h=132

//头插法建立带头结点的单链表

LinkList create1(LinkList &L){

Lnode *s;

int x;

L=(LinkList) malloc( sizeof(Lnode));//创建头结点

L->next = NULL; //初始化

printf("往链表中添加数据,99999结束\n");

scanf("%",&x);

while(x!=99999){

s = (Lnode*)malloc(sizeof(Lnode));//创建新节点

s->data = x;

s->next = L->next;

L->next = s;

scanf("%d",&x);

}

return L;

}

2)尾插法

bVbmOle?w=563&h=117

//尾插法建立单链表

LinkList create2(LinkList &L){

int x;

L=(LinkList) malloc( sizeof(Lnode));//创建尾结点

Lnode *s,*r = L;//S为插入节点指针,r为尾指针

printf("往链表中添加数据,99999结束\n");

//scanf("%",&x);

while(x!=99999){

s = (Lnode*)malloc(sizeof(Lnode));//创建新节点

scanf("%d",&x);

s->data = x;

r->next = s;

r = s; //r指向新的表尾

}

r->next = NULL;//尾节点指针置空

return L;

}

4.单链表的查找

1)按值查找

//按值查找表节点,返回节点位序,查找失败返回-1

int locateElem(LinkList L, int e){

Lnode *P = L->next;

int j=1;

while (P!=NULL&&P->data!=e){

P = P->next;

j++;

}

if(P->next == NULL && P->data == e)

return j;

else if(P->next != NULL && P->data == e)

return j;

else

return -1;

}

//按值查找表节点,返回节点指针,这是方便链表运算实现

Lnode *locateElem2(LinkList L, int e){

Lnode *P = L->next;

while (P!=NULL&&P->data!=e){

P = P->next;

}

return P;//失败则返回空指针

}

2)按序号查找

//按序号查找表节点,返回节点值

int getElem(LinkList L,int i){

int j = 1;

Lnode *P = L->next;

if(i==0)

return 0;//如果i=0,则返回头结点的值,但头结点不存值故返回0

if(i<0)

return -1;//错误序号则返回-1

while(P&&j

{

P= P->next;

j++;

}

return P->data;

}

//按序号查找表节点,返回节点指针,这是方便链表运算实现

Lnode *getElem1(LinkList L, int i){

int j = 1;

Lnode *P = L->next;

if(i==0)

return L;//如果i=0,则返回头结点

if(i<0)

return NULL;//错误序号则返回NULL

while(P&&j

{

P= P->next;

j++;

}

return P;

}

4.单链表表长

int getLength(LinkList L){

int count = 0;

while(L->next->next!=NULL)//此处指针因人而异,思想就是尾节点指针为空结束循环

{

L = L->next;

count ++;

}

return count;

}

5.插入节点

//插入节点算法1(后插,前插一般不考虑)

//指定位置插入节点

int insertElem1(LinkList L,int i,int e){

if (i<=1||i>getLength(L))

{

return 0;

}

else

{

Lnode *s,*p;

p = getElem1(L,i-1);//获取插入位置前驱

s = (Lnode*)malloc(sizeof(Lnode));//创建新节点

s->data = e;

s->next = p->next;//此句和下面那句代码不可颠倒,单链表只可找到后继,所以后继指针不能被先覆盖

p->next = s;

return 1;

}

}

//插入节点算法2

//只交换数据,不改变指针,在已知节点位置的基础上这个是最优算法

int insertElem2(LinkList L,int i,int e){

int temp;

if (i<=1||i>getLength(L))

{

return 0;

}

else

{

Lnode *s,*p;

p = getElem1(L,i);//获取插入位置前驱

s = (Lnode*)malloc(sizeof(Lnode));//创建新节点

s->data = e;

s->next = p->next;

p ->next = s;

temp = p->data;//这里做个数据交换

p->data = s->data;

s->data = temp;

return 1;

}

}

6.完整代码

#include

#include //malloc函数头文件

//单链表定义

typedef struct Lnode{

int data;

struct Lnode *next;

}Lnode,*LinkList;

//头插法建立带头结点的单链表

LinkList create1(LinkList &L){

Lnode *s;

int x;

L=(LinkList) malloc( sizeof(Lnode));//创建头结点

L->next = NULL; //初始化

printf("往链表中添加数据,99999结束\n");

scanf("%",&x);

while(x!=99999){

s = (Lnode*)malloc(sizeof(Lnode));//创建新节点

s->data = x;

s->next = L->next;

L->next = s;

scanf("%d",&x);

}

return L;

}

//尾插法建立单链表

LinkList create2(LinkList &L){

int x;

L=(LinkList) malloc( sizeof(Lnode));//创建尾结点

Lnode *s,*r = L;//S为插入节点指针,r为尾指针

printf("往链表中添加数据,99999结束\n");

//scanf("%",&x);

while(x!=99999){

s = (Lnode*)malloc(sizeof(Lnode));//创建新节点

scanf("%d",&x);

s->data = x;

r->next = s;

r = s; //r指向新的表尾

}

r->next = NULL;//尾节点指针置空

return L;

}

//求单链表表长

int getLength(LinkList L){

int count = 0;

while(L->next->next!=NULL)

{

L = L->next;

count ++;

}

return count;

}

//按序号查找表节点,返回节点值

int getElem(LinkList L,int i){

int j = 1;

Lnode *P = L->next;

if(i==0)

return 0;//如果i=0,则返回头结点的值,但头结点不存值故返回0

if(i<0)

return -1;//错误序号则返回-1

while(P&&j

{

P= P->next;

j++;

}

return P->data;

}

//按序号查找表节点,返回节点指针,这是方便链表运算实现

Lnode *getElem1(LinkList L, int i){

int j = 1;

Lnode *P = L->next;

if(i==0)

return L;//如果i=0,则返回头结点

if(i<0)

return NULL;//错误序号则返回NULL

while(P&&j

{

P= P->next;

j++;

}

return P;

}

//按值查找表节点,返回节点位序,查找失败返回-1

int locateElem(LinkList L, int e){

Lnode *P = L->next;

int j=1;

while (P!=NULL&&P->data!=e){

P = P->next;

j++;

}

if(P->next == NULL && P->data == e)

return j;

else if(P->next != NULL && P->data == e)

return j;

else

return -1;

}

//按值查找表节点,返回节点指针,这是方便链表运算实现

Lnode *locateElem2(LinkList L, int e){

Lnode *P = L->next;

while (P!=NULL&&P->data!=e){

P = P->next;

}

return P;//失败则返回空指针

}

//插入节点算法1(后插,前插一般不考虑)

//指定位置插入节点

int insertElem1(LinkList L,int i,int e){

if (i<=1||i>getLength(L))

{

return 0;

}

else

{

Lnode *s,*p;

p = getElem1(L,i-1);//获取插入位置前驱

s = (Lnode*)malloc(sizeof(Lnode));//创建新节点

s->data = e;

s->next = p->next;//此句和下面那句代码不可颠倒,单链表只可找到后继,所以后继指针不能被先覆盖

p->next = s;

return 1;

}

}

//插入节点算法2

//只交换数据,不改变指针,在已知节点位置的基础上这个是最优算法

int insertElem2(LinkList L,int i,int e){

int temp;

if (i<=1||i>getLength(L))

{

return 0;

}

else

{

Lnode *s,*p;

p = getElem1(L,i);//获取插入位置前驱

s = (Lnode*)malloc(sizeof(Lnode));//创建新节点

s->data = e;

s->next = p->next;

p ->next = s;

temp = p->data;//这里做个数据交换

p->data = s->data;

s->data = temp;

return 1;

}

}

int main(){

LinkList L,L1;

/*

create1(L);

LinkList temp = L->next;

while(temp->next != NULL)

{

printf("%d ", temp->data);

temp = temp->next;

}

printf("头插法与存数据的顺序相反\n");

*/

create2(L1);

LinkList temp2 = L1->next;

while(temp2 ->next != NULL)

{

printf("%d ", temp2->data);

temp2 = temp2->next;

}

printf("尾插法与存数据的顺序相同\n");

int length;

length = getLength(L1);

printf("单链表长度为:%d\n",length);

/*

printf("输入取值位序\n");

int i;

scanf("%d",&i);

printf("第%d位值为%d\n",i, getElem(L1,i));

printf("输入查找值\n");

int e;

scanf("%d",&e);

printf("值为:%d位序为:%d\n",e, locateElem(L1,e));

*/

//插入节点算法1

/*

int x1,x2;

printf("插入节点算法1\n");

printf("插入位置:");

scanf("%d",&x1);

printf("插入值:");

scanf("%d",&x2);

int desert = insertElem1(L1,x1,x2);

if(desert == 1)

{

printf("插入成功\n");

LinkList temp3 = L1->next;

}

else

{

printf("插入失败,位置不合法\n");

}

printf("打印链表(插入算法1)\n");

LinkList temp3 = L1->next;

while(temp3 ->next != NULL)

{

printf("%d ", temp3->data);

temp3 = temp3->next;

}

*/

//插入节点算法2

int x3,x4;

printf("插入节点算法2\n");

printf("插入位置:");

scanf("%d",&x3);

printf("插入值:");

scanf("%d",&x4);

int desert1 = insertElem2(L1,x3,x4);

if(desert1 == 1)

{

printf("插入成功\n");

LinkList temp4 = L1->next;

}

else

{

printf("插入失败,位置不合法\n");

}

printf("打印链表(插入算法2)\n");

LinkList temp4 = L1->next;

while(temp4 ->next != NULL)

{

printf("%d ", temp4->data);

temp4 = temp4->next;

}

return 0;

}

7.小结

单链表作为链表中最简单的一种,摆脱了顺序表对空间的束缚,可以很好的支持动态操作。但是其问题也很明显,每个节点只能找到其直接后继,而找不到其前一节点。在查找时需要从表头开始遍历表,会增加时间复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值