数据结构 单链表

来源:互联网 发布:xd mac 破解版 编辑:程序博客网 时间:2024/06/05 17:09
  1. 线性链表
  2. 静态链表(数组)/动态链表(malloc)
  3. 循环链表
  4. 双向链表/单链表
    1 线性链表的基本操作
    顺序存储方式的优点:
    1)随机存取
    2)不需要额外增加空间以表示结点间的逻辑关系
    缺点:
    1)插入删除效率低
    2)只能利用连续空间,不能利用小块空间
    3)静态存储分配。表长变化大时难以确定表长的规模
#include <iostream>#include <stdio.h>#include <stdlib.h>#define OVERFLOW -2using namespace std;typedef int Elemtype;typedef struct node{Elemtype data;struct node *next;}node,*linklist;//建立单链表//1.头插 2.尾插void createList_L(linklist &l){l=(linklist )malloc(sizeof(node));linklist p=l,q;int x;scanf ("%d",&x);while (x!=-999){q=(linklist )malloc(sizeof(node));q->data=x;p->next=q;p=q;scanf ("%d",&x);}q->next=NULL;}//算法2.11void createList_Lhead(linklist &l){l=(linklist )malloc(sizeof(node));linklist p;l->next=NULL;int x;scanf ("%d",&x);while (x!=-999){p=(linklist )malloc(sizeof(node));p->data=x;p->next=l->next;l->next=p;scanf ("%d",&x);}}void displayList_L(linklist &l){linklist p=l->next;while (p!=NULL){printf ("%d ",p->data);p=p->next;}printf ("\n");}//查找运算//1. 按照序号查找 2、按值查找linklist getElem(linklist &l,int i){int j=1;linklist p=l->next;while (p!=NULL&&j<i){p=p->next;j++;}return p;}linklist getElem_2(linklist &l,Elemtype e){linklist p=l->next;while (p!=NULL&&p->data!=e){p=p->next;}if (!p){printf("没有该元素\n");return NULL;//返回值类型为指针}return p;}int listLength(linklist &l){int count =0;linklist p=l->next;while (p){p=p->next;count ++;}return count;}//插入运算//1.指定节点前、后 2.指定位置前、后void listInsert_Lafter(linklist &p,Elemtype e){linklist q;q=(linklist )malloc (sizeof(node));q->data=e;q->next=p->next;p->next=q;}void listInsert_Lbefore(linklist &l,linklist p,Elemtype e){linklist q=l;while (q->next!=p) q=q->next;listInsert_Lafter(q,e);}void listInsert_Lbefore_2(linklist &l,linklist p,Elemtype e){//仍然将Q插到P的后面,然后交换数据域!很聪明的前插方式,不用循环查找前驱了linklist q;q=(linklist )malloc (sizeof(node));q->next=p->next;p->next=q;q->data=p->data;p->data=e;}//在第i个元素之前插入eint listInsert_L_i(linklist &l,int i,Elemtype e){int j=0;//必须从头结点开始linklist p=l;//if (i<1||i>listLength(l)){//printf("position error !\n");//return 0;//}while (p&&j<i-1) {//为什么这里是P?因为I可以是1--length+1p=p->next;j++;}if (!p||j>i-1){//p为空是i太大,j>i-1是i太小printf("position error \n");return 0;}linklist q;q=(linklist )malloc (sizeof(node));q->data=e;q->next=p->next;p->next=q;return 1;}//在值为y的结点前插入eint listInsert_L_y(linklist &l,Elemtype y,Elemtype e){linklist p=l;while (p->next&&p->next->data!=y){//如果P->next为空则Y元素必定不存在,注意这里与上一个插入的区别p=p->next;}if (!p){printf ("元素不存在\n");return 0;}linklist q;q=(linklist )malloc (sizeof(node));q->data=e;q->next=p->next;p->next=q;}//删除//1、给定结点2、给定位置//注意:1、被删除结点是否存在2、释放存储空间int listDelete_L(linklist &l,linklist &p){linklist q=l;while (q&&q->next!=p) q=q->next;if (!q) {printf ("结点不存在\n");return 0;}q->next=p->next;free(p);return 1;}int listDelete_L_i(linklist &l,int i,Elemtype &e){linklist p=l;int j=0;while (p->next&&j<i-1){    //查找第I-1个结点p=p->next;j++;}if (!p->next||j>i-1){printf ("position error\n");return 0;}linklist q=p->next;p->next=q->next;e=q->data;free(q);return 1;}int main(){linklist l;createList_L(l);displayList_L(l);Elemtype e;listDelete_L_i(l,3,e);displayList_L(l);    return 0;}

练习题,不调用函数

//1.删除单链表l中的重复结点int deleteDupNode(linklist &l){linklist p=l->next,q=p,k;if (!p) return 0;//空链直接返回while (p->next){while (q->next){if (q->next->data==p->data){k=q->next;q->next=k->next;free(k);}else q=q->next;}p=p->next;q=p;}return 1;}
//2.逆置单链表lvoid flipL(linklist &l){linklist p=l->next,q=p;l->next=NULL;//分离头结点while (p){p=p->next;//q指向当前断链的头结点,p指向待分离链的头结点q->next=l->next;l->next=q;q=p;}}
//3.非递增单链表ab,融合成非递增有序单链表clinklist unionL(linklist &a,linklist &b){linklist c=a;linklist pa=a->next,pb=b->next,pc=c;while (pa&&pb){if (pa->data > pb->data){pc->next=pb;pc=pc->next;//pc始终指向C链的尾pb=pb->next;}else {pc->next=pa;pc=pc->next;//pc始终指向C链的尾pa=pa->next;}}if(pa){pc->next=pa;}if(pb){pc->next=pb;}//pc->next=pa?pa:pb;free(b);return c;}
//5.对不带头结点的L就地逆置void createList_Lnohead(linklist &l){l=NULL;linklist p,q;int x;scanf ("%d",&x);while (x!=-999){q=(linklist)malloc(sizeof(node));q->data=x;if (!l){p=q;l=q;}else{p->next=q;q->next=NULL;p=q;}scanf ("%d",&x);}}void displayList_Lnohead(linklist &l){linklist p=l;while (p!=NULL){printf ("%d ",p->data);p=p->next;}printf ("\n");}void flip_Lnohead(linklist &l){linklist p,q;q=p=l;//可以连续赋值,从左到右l=NULL;//分离头指针while (p){p=q->next;q->next=l;l=q;q=p;}}
//6.对单链表l进行排序// 冒泡for void sort_Lfor(linklist &l){    linklist p,q;    p=l->next;q=p->next;    int t;for (int i=0;i<listLength(l)-1;i++){for (int j=0;j<listLength(l)-1-i;j++){if (p->data >q->data){t=p->data;p->data=q->data;q->data=t;}p=p->next;q=q->next;}p=l->next;q=p->next;}}
//7.单链表la,lb存储两个字符串,找出la中第一个不在lb中出现的字符int haha(linklist &la,linklist &lb){linklist pa=la->next;int locate_L(linklist &l,linklist p);while (pa){if (locate_L(lb,pa))pa=pa->next;elsereturn pa->data;}}int locate_L(linklist &l,linklist p){linklist q=l->next;while (q){if (q->data==p->data)return 1;q=q->next;}return 0;}
//8.递增有序la,lb,求交集lclinklist jiaoji(linklist &la,linklist &lb){linklist pa=la->next,pb=lb->next,lc,pc;lc=(linklist )malloc(sizeof(node));lc->next=NULL;pc=lc;while (pa&&pb){//如果两个元素相等则连接到lc上,否则比较大小后后移较小元素if (pa->data > pb->data)pb=pb->next;if (pa->data < pb->data)pa=pa->next;if (pa->data==pb->data){pc=(linklist )malloc (sizeof(node));pc->data=pa->data;pc->next=lc->next;lc->next=pc;pa=pa->next;pb=pb->next;}}return lc;}
//9.两个字符串la/lb,判断lb是否是la的子串(一个字符串中若干的字符称为子串)int haha(linklist &la,linklist &lb){linklist pa=la->next,pb=lb->next;while (pa&&pa->data!=pb->data) pa=pa->next;if (!pa) {printf ("no\n");return 0;}while (pb&&pa->data==pb->data){ pb=pb->next;pa=pa->next;}if (!pb)printf ("yes\n");else printf ("no\n");return 1;}

这里写图片描述

//10.int DeleteandInsert(linklist &la,linklist &lb,int i,int j,int len){if (i<0||j<0||len<0) return 0;linklist p=la,q,s,t;s=lb;int k=0;while (k<i&&p){p=p->next;k++;}//P指向第I个元素if (!p) return 0;q=p;k=0;while(k<len&&q){q=q->next;k++;}//q指向被删除的最后一个元素if (!q) return 0;k=0;while(k<j-1&&s){s=s->next;k++;}//s指向被插入元素的前驱if (!s) return 0;t=s->next;s->next=p->next;p->next=q->next;q->next=t;return 1;}
//11.删除单调递增链表l中所有值大于min并且小于max的元素(如果存在这样的元素的话)//同时删除被删结点空间void deletel(linklist &l,int min,int max){linklist p=l,q;while (p->next){if (p->next->data>min&&p->next->data < max){q=p->next;p->next=q->next;free(q);}elsep=p->next;if (!p)break;}}

方法二:

int deletel(linklist &l,int min,int max){linklist p=l,q;while (p->next->data<=min&&p) p=p->next;//找到第一个被删除结点的前驱if (!p) return 0;q=p->next;while (q&&q->data<max) q=q->next;//这里q&&q->data与q->Data&&q不同,后者会报错,因为当Q指向NULL时//q->Data为错误的表达式//q指向第一个不被删除的元素p->next=q;return 1;}
//12.删除递增表L中所有值相同的多余元素void deletel(linklist &l){linklist p=l->next,q=p->next;while (q){if (p->data==q->data){p->next=q->next;free(q);q=p->next;}else {p=p->next;q=q->next;}}}

这里写图片描述

void mergeAandB(linklist &la,linklist &lb,linklist &lc){linklist pa=la->next,pb=lb->next;linklist qa=pa->next,qb=pb->next;lc=la;while (qa&&qb){pa->next=pb;pb->next=qa;pa=qa;pb=qb;qa=pa->next;qb=pb->next;}if (!qa){pa->next=pb;}if (!qb){pb->next=pa;}}

这里写图片描述

//分析:本算法的思想是,按从小到大的顺序依次把A和B的元素//插入新表的头部pc处,最后处理A或B的剩余元素.void reverse_merge(linklist &la,linklist &lb,linklist &lc){linklist pa=la->next,pb=lb->next,pc,t;pc=NULL;while (pa&&pb){if (pa->data < pb->data ){t=pa->next;pa->next=pc;pc=pa;pa=t;}else {t=pb->next;pb->next=pc;pc=pb;pb=t;}}while (pb){t=pb->next;pb->next=pc;pc=pb;pb=t;}while (pa){t=pa->next;pa->next=pc;pc=pa;pa=t;}lc=la;lc->next=pc;free(pb);}

28.

//8.递增有序la,lb,求交集lclinklist jiaoji(linklist &la,linklist &lb){linklist pa=la->next,pb=lb->next,lc,pc;lc=(linklist )malloc(sizeof(node));lc->next=NULL;pc=lc;while (pa&&pb){//如果两个元素相等则连接到lc上,否则比较大小后后移较小元素if (pa->data > pb->data)pb=pb->next;elseif (pa->data < pb->data)pa=pa->next;else{if (pc->data!=pa->data){pc=(linklist )malloc (sizeof(node));pc->data=pa->data;pc->next=lc->next;lc->next=pc;}pa=pa->next;pb=pb->next;}}return lc;}
//2.30 对于A,删去即在b又在c中出现的元素void lalblc(linklist &la,linklist &lb,linklist &lc){linklist pa=la,pb=lb->next,pc=lc->next,t;while (pa->next&&pb&&pc){if (pb->data > pc->data)pb=pb->next;elseif (pb->data < pc->data)pc=pc->next;else{    if (pa->next->data < pb->data)    pa=pa->next;    else{    while (pa->next->data == pb->data)    {    t=pa->next;    pa->next=t->next;    free(t);    }    pb=pb->next;pc=pc->next;}}}}

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

2)

2.30 void LinkList_Intersect_Delete(LinkList &A,LinkList B,LinkList C)//在链表结构上重做上题{  p=B->next;q=C->next;r=A-next;  while(p&&q&&r)  {    if(p->data<q->data) p=p->next;    else if(p->data>q->data) q=q->next;    else    {      u=p->data; //确定待删除元素u      while(r->next->data<u) r=r->next; //确定最后一个小于u的元素指针r      if(r->next->data==u)      {        s=r->next;        while(s->data==u)        {          t=s;s=s->next;free(t); //确定第一个大于u的元素指针s        }//while        r->next=s; //删除r和s之间的元素      }//if      while(p->data=u) p=p->next;      while(q->data=u) q=q->next;    }//else  }//while}//LinkList_Intersect_Delete 
0 0
原创粉丝点击