zoukankan      html  css  js  c++  java
  • 严蔚敏版《数据结构 (C语言版)》和《数据结构题集》(三)——单链表

    1. 线性链表
    2. 静态链表(数组)/动态链表(malloc)
    3. 循环链表
    4. 双向链表/单链表
      1 线性链表的基本操作
      顺序存储方式的优点:
      1)随机存取
      2)不需要额外增加空间以表示结点间的逻辑关系
      缺点:
      1)插入删除效率低
      2)只能利用连续空间,不能利用小块空间
      3)静态存储分配。表长变化大时难以确定表长的规模
      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #define OVERFLOW -2
      5 
      6 using namespace std;
      7 
      8 typedef int Elemtype;
      9 typedef struct node{
     10 Elemtype data;
     11 struct node *next;
     12 }node,*linklist;
     13 
     14 //建立单链表
     15 //1.头插 2.尾插
     16 void createList_L(linklist &l){
     17 l=(linklist )malloc(sizeof(node));
     18 linklist p=l,q;
     19 int x;
     20 scanf ("%d",&x);
     21 while (x!=-999){
     22 q=(linklist )malloc(sizeof(node));
     23 q->data=x;
     24 p->next=q;
     25 p=q;
     26 scanf ("%d",&x);
     27 }
     28 q->next=NULL;
     29 }
     30 //算法2.11
     31 void createList_Lhead(linklist &l){
     32 l=(linklist )malloc(sizeof(node));
     33 linklist p;
     34 l->next=NULL;
     35 int x;
     36 scanf ("%d",&x);
     37 while (x!=-999){
     38 p=(linklist )malloc(sizeof(node));
     39 p->data=x;
     40 p->next=l->next;
     41 l->next=p;
     42 scanf ("%d",&x);
     43 }
     44 }
     45 void displayList_L(linklist &l){
     46 linklist p=l->next;
     47 while (p!=NULL){
     48 printf ("%d ",p->data);
     49 p=p->next;
     50 }
     51 printf ("
    ");
     52 }
     53 //查找运算
     54 //1. 按照序号查找 2、按值查找
     55 linklist getElem(linklist &l,int i){
     56 int j=1;
     57 linklist p=l->next;
     58 while (p!=NULL&&j<i){
     59 p=p->next;
     60 j++;
     61 }
     62 return p;
     63 }
     64 linklist getElem_2(linklist &l,Elemtype e){
     65 linklist p=l->next;
     66 while (p!=NULL&&p->data!=e){
     67 p=p->next;
     68 }
     69 if (!p){
     70 printf("没有该元素
    ");
     71 return NULL;//返回值类型为指针
     72 }
     73 return p;
     74 }
     75 
     76 int listLength(linklist &l){
     77 int count =0;
     78 linklist p=l->next;
     79 while (p){
     80 p=p->next;
     81 count ++;
     82 }
     83 return count;
     84 }
     85 //插入运算
     86 //1.指定节点前、后 2.指定位置前、后
     87 void listInsert_Lafter(linklist &p,Elemtype e){
     88 linklist q;
     89 q=(linklist )malloc (sizeof(node));
     90 q->data=e;
     91 q->next=p->next;
     92 p->next=q;
     93 }
     94 void listInsert_Lbefore(linklist &l,linklist p,Elemtype e){
     95 linklist q=l;
     96 while (q->next!=p) q=q->next;
     97 listInsert_Lafter(q,e);
     98 }
     99 void listInsert_Lbefore_2(linklist &l,linklist p,Elemtype e){
    100 //仍然将Q插到P的后面,然后交换数据域!很聪明的前插方式,不用循环查找前驱了
    101 linklist q;
    102 q=(linklist )malloc (sizeof(node));
    103 q->next=p->next;
    104 p->next=q;
    105 q->data=p->data;
    106 p->data=e;
    107 }
    108 //在第i个元素之前插入e
    109 int listInsert_L_i(linklist &l,int i,Elemtype e){
    110 int j=0;//必须从头结点开始
    111 linklist p=l;
    112 //if (i<1||i>listLength(l)){
    113 //printf("position error !
    ");
    114 //return 0;
    115 //}
    116 while (p&&j<i-1) {
    117 //为什么这里是P?因为I可以是1--length+1
    118 p=p->next;
    119 j++;
    120 }
    121 if (!p||j>i-1){
    122 //p为空是i太大,j>i-1是i太小
    123 printf("position error 
    ");
    124 return 0;
    125 }
    126 linklist q;
    127 q=(linklist )malloc (sizeof(node));
    128 q->data=e;
    129 q->next=p->next;
    130 p->next=q;
    131 return 1;
    132 }
    133 //在值为y的结点前插入e
    134 int listInsert_L_y(linklist &l,Elemtype y,Elemtype e){
    135 linklist p=l;
    136 while (p->next&&p->next->data!=y){
    137 //如果P->next为空则Y元素必定不存在,注意这里与上一个插入的区别
    138 p=p->next;
    139 }
    140 if (!p){
    141 printf ("元素不存在
    ");
    142 return 0;
    143 }
    144 linklist q;
    145 q=(linklist )malloc (sizeof(node));
    146 q->data=e;
    147 q->next=p->next;
    148 p->next=q;
    149 
    150 }
    151 //删除
    152 //1、给定结点2、给定位置
    153 //注意:1、被删除结点是否存在2、释放存储空间
    154 int listDelete_L(linklist &l,linklist &p){
    155 linklist q=l;
    156 while (q&&q->next!=p) q=q->next;
    157 if (!q) {
    158 printf ("结点不存在
    ");
    159 return 0;
    160 }
    161 q->next=p->next;
    162 free(p);
    163 return 1;
    164 }
    165 int listDelete_L_i(linklist &l,int i,Elemtype &e){
    166 linklist p=l;
    167 int j=0;
    168 while (p->next&&j<i-1){
    169     //查找第I-1个结点
    170 p=p->next;
    171 j++;
    172 }
    173 if (!p->next||j>i-1){
    174 printf ("position error
    ");
    175 return 0;
    176 }
    177 linklist q=p->next;
    178 p->next=q->next;
    179 e=q->data;
    180 free(q);
    181 return 1;
    182 }
    183 int main()
    184 {
    185 linklist l;
    186 createList_L(l);
    187 displayList_L(l);
    188 Elemtype e;
    189 listDelete_L_i(l,3,e);
    190 displayList_L(l);
    191 
    192     return 0;
    193 }

    练习题,不调用函数

      1 //1.删除单链表l中的重复结点
      2 int deleteDupNode(linklist &l){
      3 linklist p=l->next,q=p,k;
      4 if (!p) 
      5 return 0;//空链直接返回
      6 while (p->next){
      7 while (q->next){
      8 if (q->next->data==p->data){
      9 k=q->next;
     10 q->next=k->next;
     11 free(k);
     12 }
     13 else 
     14 q=q->next;
     15 }
     16 p=p->next;
     17 q=p;
     18 }
     19 
     20 return 1;
     21 }
     22 //2.逆置单链表l
     23 void flipL(linklist &l){
     24 linklist p=l->next,q=p;
     25 l->next=NULL;//分离头结点
     26 while (p){
     27 p=p->next;//q指向当前断链的头结点,p指向待分离链的头结点
     28 q->next=l->next;
     29 l->next=q;
     30 q=p;
     31 }
     32 }
     33 //3.非递增单链表ab,融合成非递增有序单链表c
     34 linklist unionL(linklist &a,linklist &b){
     35 linklist c=a;
     36 linklist pa=a->next,pb=b->next,pc=c;
     37 while (pa&&pb){
     38 if (pa->data > pb->data){
     39 pc->next=pb;
     40 pc=pc->next;//pc始终指向C链的尾
     41 pb=pb->next;
     42 }
     43 else {
     44 pc->next=pa;
     45 pc=pc->next;//pc始终指向C链的尾
     46 pa=pa->next;
     47 }
     48 }
     49 if(pa){
     50 pc->next=pa;
     51 }
     52 if(pb){
     53 pc->next=pb;
     54 }
     55 //pc->next=pa?pa:pb;
     56 free(b);
     57 return c;
     58 }
     59 //5.对不带头结点的L就地逆置
     60 void createList_Lnohead(linklist &l){
     61 l=NULL;
     62 linklist p,q;
     63 int x;
     64 scanf ("%d",&x);
     65 while (x!=-999){
     66 q=(linklist)malloc(sizeof(node));
     67 q->data=x;
     68 if (!l){
     69 p=q;l=q;
     70 }else{
     71 p->next=q;
     72 q->next=NULL;
     73 p=q;
     74 }
     75 scanf ("%d",&x);
     76 }
     77 }
     78 void displayList_Lnohead(linklist &l){
     79 linklist p=l;
     80 while (p!=NULL){
     81 printf ("%d ",p->data);
     82 p=p->next;
     83 }
     84 printf ("
    ");
     85 }
     86 void flip_Lnohead(linklist &l){
     87 linklist p,q;
     88 q=p=l;//可以连续赋值,从左到右
     89 l=NULL;//分离头指针
     90 while (p){
     91 p=q->next;
     92 q->next=l;
     93 l=q;
     94 q=p;
     95 }
     96 }
     97 //6.对单链表l进行排序
     98 // 冒泡for 
     99 void sort_Lfor(linklist &l){
    100     linklist p,q;
    101     p=l->next;q=p->next;
    102     int t;
    103 for (int i=0;i<listLength(l)-1;i++){
    104 for (int j=0;j<listLength(l)-1-i;j++){
    105 if (p->data >q->data){
    106 t=p->data;
    107 p->data=q->data;
    108 q->data=t;
    109 }
    110 p=p->next;
    111 q=q->next;
    112 }
    113 p=l->next;
    114 q=p->next;
    115 }
    116 }
    117 //7.单链表la,lb存储两个字符串,找出la中第一个不在lb中出现的字符
    118 int haha(linklist &la,linklist &lb){
    119 linklist pa=la->next;
    120 int locate_L(linklist &l,linklist p);
    121 while (pa){
    122 if (locate_L(lb,pa))
    123 pa=pa->next;
    124 else
    125 return pa->data;
    126 }
    127 }
    128 int locate_L(linklist &l,linklist p){
    129 linklist q=l->next;
    130 while (q){
    131 if (q->data==p->data)
    132 return 1;
    133 q=q->next;
    134 }
    135 return 0;
    136 }
    137 //8.递增有序la,lb,求交集lc
    138 linklist jiaoji(linklist &la,linklist &lb){
    139 linklist pa=la->next,pb=lb->next,lc,pc;
    140 lc=(linklist )malloc(sizeof(node));lc->next=NULL;
    141 pc=lc;
    142 while (pa&&pb){
    143 //如果两个元素相等则连接到lc上,否则比较大小后后移较小元素
    144 if (pa->data > pb->data)
    145 pb=pb->next;
    146 if (pa->data < pb->data)
    147 pa=pa->next;
    148 if (pa->data==pb->data){
    149 pc=(linklist )malloc (sizeof(node));
    150 pc->data=pa->data;
    151 pc->next=lc->next;
    152 lc->next=pc;
    153 pa=pa->next;pb=pb->next;
    154 }
    155 }
    156 return lc;
    157 }
    158 //9.两个字符串la/lb,判断lb是否是la的子串(一个字符串中若干的字符称为子串)
    159 int haha(linklist &la,linklist &lb){
    160 linklist pa=la->next,pb=lb->next;
    161 while (pa&&pa->data!=pb->data) pa=pa->next;
    162 if (!pa) {
    163 printf ("no
    ");
    164 return 0;
    165 }
    166 while (pb&&pa->data==pb->data){
    167  pb=pb->next;pa=pa->next;
    168 }
    169 if (!pb)printf ("yes
    ");
    170 else printf ("no
    ");
    171 return 1;
    172 }

    这里写图片描述

     1 //10.
     2 int DeleteandInsert(linklist &la,linklist &lb,int i,int j,int len){
     3 if (i<0||j<0||len<0) return 0;
     4 linklist p=la,q,s,t;
     5 s=lb;
     6 int k=0;
     7 while (k<i&&p){
     8 p=p->next;k++;
     9 }//P指向第I个元素
    10 if (!p) return 0;
    11 q=p;
    12 k=0;
    13 while(k<len&&q){
    14 q=q->next;k++;
    15 }//q指向被删除的最后一个元素
    16 if (!q) return 0;
    17 k=0;
    18 while(k<j-1&&s){
    19 s=s->next;k++;
    20 }//s指向被插入元素的前驱
    21 if (!s) return 0;
    22 t=s->next;
    23 s->next=p->next;
    24 p->next=q->next;
    25 q->next=t;
    26 return 1;
    27 }
    28 //11.删除单调递增链表l中所有值大于min并且小于max的元素(如果存在这样的元素的话)
    29 //同时删除被删结点空间
    30 void deletel(linklist &l,int min,int max){
    31 linklist p=l,q;
    32 while (p->next){
    33 if (p->next->data>min&&p->next->data < max){
    34 q=p->next;
    35 p->next=q->next;
    36 free(q);
    37 }else
    38 p=p->next;
    39 if (!p)
    40 break;
    41 }
    42 }

    方法二:

     1 int deletel(linklist &l,int min,int max){
     2 linklist p=l,q;
     3 while (p->next->data<=min&&p) p=p->next;
     4 //找到第一个被删除结点的前驱
     5 if (!p) return 0;
     6 q=p->next;
     7 while (q&&q->data<max) q=q->next;
     8 //这里q&&q->data与q->Data&&q不同,后者会报错,因为当Q指向NULL时
     9 //q->Data为错误的表达式
    10 //q指向第一个不被删除的元素
    11 p->next=q;
    12 return 1;
    13 }
    14 //12.删除递增表L中所有值相同的多余元素
    15 void deletel(linklist &l){
    16 linklist p=l->next,q=p->next;
    17 while (q){
    18 if (p->data==q->data){
    19 p->next=q->next;
    20 free(q);
    21 q=p->next;
    22 }else {
    23 p=p->next;
    24 q=q->next;
    25 }
    26 }
    27 }

    这里写图片描述

     1 void mergeAandB(linklist &la,linklist &lb,linklist &lc){
     2 linklist pa=la->next,pb=lb->next;
     3 linklist qa=pa->next,qb=pb->next;
     4 lc=la;
     5 while (qa&&qb){
     6 pa->next=pb;
     7 pb->next=qa;
     8 pa=qa;
     9 pb=qb;
    10 qa=pa->next;
    11 qb=pb->next;
    12 }
    13 if (!qa){
    14 pa->next=pb;
    15 }
    16 if (!qb){
    17 pb->next=pa;
    18 }
    19 }

    这里写图片描述

     1 //分析:本算法的思想是,按从小到大的顺序依次把A和B的元素
     2 //插入新表的头部pc处,最后处理A或B的剩余元素.
     3 void reverse_merge(linklist &la,linklist &lb,linklist &lc){
     4 linklist pa=la->next,pb=lb->next,pc,t;
     5 pc=NULL;
     6 while (pa&&pb){
     7 if (pa->data < pb->data ){
     8 t=pa->next;
     9 pa->next=pc;
    10 pc=pa;
    11 pa=t;
    12 }
    13 else {
    14 t=pb->next;
    15 pb->next=pc;
    16 pc=pb;
    17 pb=t;
    18 }
    19 }
    20 while (pb){
    21 t=pb->next;
    22 pb->next=pc;
    23 pc=pb;
    24 pb=t;
    25 }
    26 while (pa){
    27 t=pa->next;
    28 pa->next=pc;
    29 pc=pa;
    30 pa=t;
    31 }
    32 lc=la;
    33 lc->next=pc;
    34 free(pb);
    35 
    36 }

    28.

     1 //8.递增有序la,lb,求交集lc
     2 linklist jiaoji(linklist &la,linklist &lb){
     3 linklist pa=la->next,pb=lb->next,lc,pc;
     4 lc=(linklist )malloc(sizeof(node));lc->next=NULL;
     5 pc=lc;
     6 while (pa&&pb){
     7 //如果两个元素相等则连接到lc上,否则比较大小后后移较小元素
     8 if (pa->data > pb->data)
     9 pb=pb->next;
    10 else
    11 if (pa->data < pb->data)
    12 pa=pa->next;
    13 else{
    14 if (pc->data!=pa->data){
    15 pc=(linklist )malloc (sizeof(node));
    16 pc->data=pa->data;
    17 pc->next=lc->next;
    18 lc->next=pc;
    19 }
    20 pa=pa->next;pb=pb->next;
    21 }
    22 
    23 }
    24 return lc;
    25 }
    26 //2.30 对于A,删去即在b又在c中出现的元素
    27 void lalblc(linklist &la,linklist &lb,linklist &lc){
    28 linklist pa=la,pb=lb->next,pc=lc->next,t;
    29 while (pa->next&&pb&&pc){
    30 if (pb->data > pc->data)
    31 pb=pb->next;
    32 else
    33 if (pb->data < pc->data)
    34 pc=pc->next;
    35 else
    36 {
    37     if (pa->next->data < pb->data)
    38     pa=pa->next;
    39     else{
    40     while (pa->next->data == pb->data)
    41     {
    42     t=pa->next;
    43     pa->next=t->next;
    44     free(t);
    45     }
    46     pb=pb->next;pc=pc->next;
    47 }
    48 }
    49 }
    50 }

    //思路:
    1.对b和c进行比较:不等时较小数后移;相等时再对a进行比较:a小时移动a,a大时bc移动,相等时对a进行删除。注意这里用while判断pa->next->data == pb->data,因为a中可能有重复的被删除元素。

    2)

     1 void LinkList_Intersect_Delete(LinkList &A,LinkList B,LinkList C)//在链表结构上重做上题
     2 {
     3   p=B->next;q=C->next;r=A-next;
     4   while(p&&q&&r)
     5   {
     6     if(p->data<q->data) p=p->next;
     7     else if(p->data>q->data) q=q->next;
     8     else
     9     {
    10       u=p->data; //确定待删除元素u
    11       while(r->next->data<u) r=r->next; //确定最后一个小于u的元素指针r
    12       if(r->next->data==u)
    13       {
    14         s=r->next;
    15         while(s->data==u)
    16         {
    17           t=s;s=s->next;free(t); //确定第一个大于u的元素指针s
    18         }//while
    19         r->next=s; //删除r和s之间的元素
    20       }//if
    21       while(p->data=u) p=p->next;
    22       while(q->data=u) q=q->next;
    23     }//else
    24   }//while
    25 }//LinkList_Intersect_Delete 
     
  • 相关阅读:
    Java实验四
    Java第八周学习总结
    Java实验三
    输入输出练习
    第七周
    20145113 实验二 Java面向对象程序设计
    2020-2021-1 20209306 《linux内核原理与分析》第九周作业
    2020-2021-1 20209306 《linux内核原理与分析》第八周作业
    2020-2021-1 20209306 《linux内核原理与分析》第七周作业
    2020-2021-1 20209306 《linux内核原理与分析》第六周作业
  • 原文地址:https://www.cnblogs.com/twomeng/p/9476537.html
Copyright © 2011-2022 走看看