首页 > 编程知识 正文

单链表的删除算法,求单链表的长度的算法

时间:2023-05-06 19:04:53 阅读:260636 作者:854

算法描述:

  在《啊哈算法》上有介绍模拟链表的实现。链表这种数据结构可以通过数组来实现,我们需要两个数组,其中一个数组data存放数据,即数据域。另外一个数组right用来存放每一个数的右边的数的位置,即指针域。

  在上图中,列如data[3]的下一个元素是data[4],下标为4 ,所以right[3]的值为4。又因为data[9]后没有元素,所以right[9]的值用0表示。
  如果我们要在data[4]数字8之前插入数字6,只需将6放到data数组末尾data[10],接下来将right[3]指向10,将right[10]指向4。

算法实现(上):

代码参考了《啊哈算法》上的实现,但实际上书上的代码是有问题的。

/*核心思路:查找是否存在一个节点的下一个节点的数据大于待插入的节点,即data[right[t]]>data[len]如果找到了,就修改right指针域。最后根据right指针域打印其数据域的值*/#include <stdio.h>int data[101];int right[101];//每个节点都有一个指针域,所以这里的数组长度要和data数组一样长int main(){/*n为用户首次录入的节点总数,用于控制初始化节点时的循环次数len为当前节点总数,为方便操作,data[0]和right[0]不放内容,从下标1开始遍历,因此data[len]就是最后一个元素*/ int n,i,len,t; scanf("%d",&n); //初始化数组data for(i = 1;i<=n;i++){ scanf("%d",&data[i]); } len = n; //初始化数组right for(i = 1;i<=n;i++){ if(i!=n){ right[i] = i+1; }else{ right[i] = 0;//用0表示没有下一个元素 } } //在data的末尾添加一个数 len++; scanf("%d",&data[len]); /* 通过遍历指针域,当找到某个节点的数据值大于插入的节点data[len]时,调整指针域的指向。 直到指针域遍历完成为止 */ t = 1; while(t!=0){ if(data[right[t]]>data[len]){ right[len] = right[t]; right[t] = len; break; } t = right[t]; } t = 1; while(t!=0){ printf("%d ",data[t]); t = right[t]; } //等待用户键盘录入,以起到暂停程序目的 getchar(); getchar(); return 0;} 程序验证: 第一组:31 3 54输出:1 3 4 5第二组:31 3 57输出:1 3 5第三组:131输出:3

测试发现,当用户要插入的数据小于data[1]或者大于最后一个数时,结果输出有误。
结合下面的代码段和这张图可知,当待插入数小于第一个数时,程序是将data[2]和插入数据进行比较;若是待插入的数大于最后一个数,当程序执行到right[t]==0时,由于data[0]未定义,程序也将不会进入if语句段修改其指针域。

t = 1; while(t!=0){ if(data[right[t]]>data[len])

算法修正

既然当待插入数大于最后一个数时,没有进入if(data[right[t]]>data[len])语句块,那么只需做一个标记,当未进入该语句块后,就修改最后一个数和倒数第二个数的指针域。
当插入数小于第一个数时,比如对于下面这种情况,由于right数组表示的是指向下一个节点的值,所以直接更改right[1]的值并不正确。

后来想到了可以添加一个头节点,即添加一个right[0],这样当插入数小于第一个数时,只需修改right[0]和right[len]两个指针域即可。

算法实现(下): /*核心思路:查找是否存在一个节点的下一个节点的数据大于待插入的节点,即data[right[t]]>data[len]如果找到了,就修改right指针域。最后根据right指针域打印其数据域的值*/#include <stdio.h>int data[101];int right[101];//每个节点都有一个指针域,所以这里的数组长度要和data数组一样长int main(){/*n为用户首次录入的节点总数,用于控制初始化节点时的循环次数len为当前节点总数,为方便操作,data[0]和right[0]不放内容,从下标1开始遍历,因此data[len]就是最后一个元素*/ int n,i,len,t; int flag = 1; scanf("%d",&n); //初始化数组data for(i = 1;i<=n;i++){ scanf("%d",&data[i]); } len = n; //初始化数组right for(i = 0;i<=n;i++){ if(i!=n){ right[i] = i+1; }else{ right[i] = 0;//用0表示没有下一个元素 } } //在data的末尾添加一个数 len++; scanf("%d",&data[len]); /* 通过遍历指针域,当找到某个节点的数据值大于插入的节点data[len]时,调整指针域的指向。 直到指针域遍历完成为止 */ t = 1; //对插入节点小于第一个节点的情况做特殊处理。(这里放在if..else里是出于无需再走循环的目的) if(data[len]<data[1]){ right[0] = len; right[len] = 1;}else{while(t!=0){ if(data[right[t]]>data[len]){ flag = 0; right[len] = right[t]; right[t] = len; break; } t = right[t]; } //插入节点大于最后一个节点的情况 if(flag == 1){ right[len] = 0; /*这里只做简单处理,也可以查找right[t]==0的节点修改其指针域, 只需在上面循环中加入if(right[t]==0){temp = t;} 这里再改成right[temp] = len; */ right[len-1] = len; }}//t为right[0]头节点指向的首节点的下标 t = right[0]; while(t!=0){ printf("%d ",data[t]); t = right[t]; } //等待用户键盘录入,以起到暂停程序目的 getchar(); getchar(); return 0;} 程序验证: 第一组:31 3 54输出:1 3 4 5 第二组:31 3 57输出:1 3 5 7 第三组:131输出:1 3

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。