08、单链表编程考点
单链表编程考点
1、将单链表的第一个结点放在单链表的最后一个结点的后面
/* 设h是无头结点的单链表,如果线性表h的长度不小于2,则将首元结点删除并插入到表尾 将单链表的第一个结点放在单链表的最后一个结点的后面 */ typedef struct node { elementype data; struct node *next; }*linklist; void change(linklist &h) //linklist &h等价于struct node *&h,这样就可以修改指针h的值;此时不需要return返回已经修改的单链表的值 { linklist p,q; //linklist p,q等价于struct node *p、struct node *q; if(h && h->next) //如果链表中有不少于2个结点 { q = h; //令p指向第1个结点h h = h->next; //令h指向第2个结点 p = h; //令p指向第2个结点 while(p->next) //第一次循环时,判断第2个结点的指针域是否为空,如果为空则只有两个结点,则不需要找到最后的一个结点,否则一直循环,找到最后一个结点为止 p = p->next; //顺着p开始往下找,一直找到最后一个结点 p->next = q; //将第一个结点接在最后一个结点后面 q->next = NULL; //新的尾结点没有后继,置后继为空 } } /* 分析:1、在if判断语句中h为单链表的某一指针指向单链表中的某一个结点 2、q = h;此语句的含义是另外一个指针q与指针h同时指向同一个结点 3、h = h->next;此语句中的h->next所表示的含义是h->next指向单链表中h指针指向的下一个结点,与此同时h指针和h->next指针同时指向该结点 */
typedef struct node { elementype data; struct node *next; }*Linklist; Linklist mynode(LinkList L) //L是不带头结点的单链表的头指针 { if(L && L->next) //如果链表中有不少于2个结点 { q = L; //令p指向第1个结点h L = L->next; //令h指向第2个结点 p = L; //令p指向第2个结点 while(p->next) p = p->next; //顺着p开始往下找,一直找到最后一个结点 p->next = q; //将第一个结点接在最后一个结点后面 q->next = NULL; //新的尾结点没有后继,置后继为空 } return L; }
2、实现单链表的删除算法,删除成功返回1,删除失败返回0
/*实现单链表的删除算法,删除成功返回1,删除失败返回0*/ typedef struct node { elementype data; struct node *next; }*LinkList, LNode; int ListDelete(LinkList L, int i, ElemType *s) //s是存储将要删除的值,i是将要被删除元素的指定位置 { LNode *p,*q; //定义了两个新的指针变量p、q; int j; p = L; //p指向L单链表的第一个结点元素 j = 0; while((p->next != NULL)&&(j < i-1)) //j < i-1此处的判断条件是i-1的原因是当最后一次,不满足条件之前,j的值自动增加了一位 { p = p->next; //而我们进行删除操作的前提是找到被删除结点元素的前驱结点 j++; } if(p->next == NULL || j > i-1) return 0; //如果if语句成立,将执行return 0;语句,运行过程终止 q=p->next; //否则将q指针指向p->next指针所指的结点,即指向被删除结点元素 *s = q->data; p->next = q->next; //此语句将指定位置的结点删除,p->next所代表的是被删结点元素的前驱结点的next指针域,而q->next指向被删结点元素的后继结点 free(q); //释放结点占有的存储空间 return 1; }
3、尾插法建立单链表
//尾插法建立单链表 typedef struct node { int data; struct node *next; }lklist; void lklistcreate(lklist *&head ,int n) //n表示单链表的长度 { lklist *q; //定义一个新的结点指针 for(i = 1;i<=n;i++) { p=(lklist *)malloc(sizeof(lklist)); //创建一个新的结点 scanf("%d",&(p->data)); //获取该结点的数值 p->next = NULL; if(i==1) head = q = p; //head = q = p;该语句表示头指针head,新的结点指针q都指向结点p; else { q->next = p; //注意:定义的新的结点指针q的作用是通过移动该指针的指向,来实现链表的创建,将q结点的next指针域指向最新创建的结点 q=p; //将结点连接以后,再改变q指针的指向,为下一次新结点的创建作好准备 } } }
4、逆转线性单链表,采用是头插法
//逆转线性单链表,采用是头插法 typedef struct node //就地逆置单链表 { elemtype data; struct node *next; }node; node *Reverse (node *head) //head是带头结点的单链表 { node *p ,*q; p = head->next; //p指向第一个元素 head->next=NULL; //保留第一个元素,将头结点的指针域置空 while(p!=NULL) //将原链表的元素用头插法插入新的链表中 { q=p; //令q指向链表的当前第一个元素 p=p->next; //p指针后移 q->next = head->next; //在新表中插入结点q head->next = q; } return head; }
5、在带头结点的单链表L中,删除所有值为x的结点
//在带头结点的单链表L中,删除所有值为x的结点 typedef struct LNode { Elemtype data; struct LNode *next; }LNode, *Linklist; void delete(Linklist &L ,ElemType x) { LNode *q=L; LNode p=L->next; //初始化p指向第一个结点,q始终指向p结点的前驱 while(p!=NULL) { if(p->data == x) //若p指针指向当前结点的值等于x { q->next = p->next; free(p); //删除该结点,并修改p指针 p=q->next; //寻找链表中下一个值为x的结点 } else { q=p; p=p->next; //先使q后移,p向后移动 } } }
6、有序递增序列,删除所有值大于mink且小于maxk的元素
//有序递增序列,删除所有值大于mink且小于maxk的元素 typedef struct node //就地逆置单链表 { elemtype data; struct node *next; }node; void Delete_Between(node *head, int mink, int maxk) { node *p = head, *q; while(p->next->data <= mink) //p是最后一个不大于mink的元素 p=p->next; if(p->next) //如果还有比mink更大的元素 { q=p->next; while(q->data<maxk) //q是第一个不小于maxk的元素 q=q->next; //while循环结束以后,q指向比maxk值还大的结点元素 p->next = q; //此语句是删除所有值大于mink且小于maxk的元素 } }
7、将带头结点单链表h1和h2合并成升序排列的单链表
//将带头结点单链表h1和h2合并成升序排列的单链表 typedef struct L { int data; struct L *next; }LinkL; LinkL *mergeList(LinkL *h1, LinkL *h2) { LinkL *h, *Next, *q; h=h1; Next = h; h1=h1->next; //表h1的第一个结点 h2=h2->next; //表h2的第一个结点 while(h1 != NULL && h2 != NULL) //如果表h1和h2均不为空表 { if(h1->data <= h2->data) //如果h1指针所指向当前结点的值小于h2 { //指针所指向的当前结点的值 q=h1; //则令q暂存h1指针所指向的结点 h1=h1->next; //h1指针向后移动 } else //如果h2指针所指向当前结点的值小于h1 { //指针所指向的当前结点的值 q=h2; //则令q暂存h2指针所指向的结点 h2-h2->next; //h2指针向后移动 } Next->next = q; //将指针p所指向的结点接在Next指针所指的结点后面 Next = q; } if(h1 == NULL) //如果原h2链表中所有结点已插入但是原h1链表还有结点没插完,则直接把剩余部分接在next指针后面。要是原h1表的所有结点已经全部插完但是h2还有结点没插完,亦是如此 Next->next = h2; if(h2 == NULL) Next->next = h1; return h; //返回新表的指针 }
8、用单链表lc表示集合C,分别将la中的元素取出,再在lb中进行查找,如果在lb中出现,则将其插入到lc中
//将单链表A分解成一个小于零的单链表和大于零的单链表 typedef struct node { elemtype data; struct node *next; }*LinkList,Linknode; void decompose(LinkList La,LinkList Lb,LinkList Lc) { Linknode *p; Lc=(Linknode *)malloc(sizeof(Linknode)); Lc->next = NULL; //表C的头结点的next域置空 p=La->next; //令p指向表A的第一个元素结点 Lb=La; //令Lb指向表La Lb->next = NULL; //令表La的next域置空 while(p) //遍历原表A { La=p->next; //令La暂存p结点的后继指针 if(p->data >0) //如果p结点值大于0,则接在表C后面 { p->next=Lc->next; Lc->next = p; } else{ //如果p结点的值小于0,则接在表B后面 p->next =Lb->next; Lb->next = p; } p=La; //令p指向原p所指向的结点的下一个位置 } }
9、将单链表A分解成一个小于零的单链表和大于零的单链表
//用单链表lc表示集合C,分别将la中的元素取出,再在lb中进行查找,如果在lb中出现,则将其插入到lc中 typedef struct node { elemtype data; struct node *next; }*LinkList,LNode; void interaction(LinkList la, LinkList lb, LinkList &lc) { LinkList pa ,pb, pc; lc = new LNode(); //生成lc的头结点 pc=lc; //pc永远指向lc的尾结点 pa=la->next; //pa指向la的第一个元素 while(pa) { pb=lb->next; //pa指向lb表的第一个元素 while(pb && pb->data != pa->data) pb=pb->next; //在pb中查找元素,使其值等于pa->data if(pb) //如果存在这样的元素 { pc->next = new LNode(); //生成lc新的尾结点 pc = pc->next; //pc指向新的尾结点 pc->data= pa->data; //将pa->data复制到pc中 } pa=pa->next; //继续比较pa表的下一个结点元素 } pc->next =NULL; //pc为尾结点,pc表比较完成后,置pc后继为空 }
10、已知指针hb和ha分别指向两个单链表的头结点,长度为m和n,假设hc指向连接后的链表的头结点
//已知指针hb和ha分别指向两个单链表的头结点,长度为m和n,假设hc指向连接后的链表的头结点 typedef struct node { elemtype data; struct node *next; }LinkList; void ListConcat(LinkList ha, LinkList hb, LinkList *hc) { LinkList p; //把链表hb接在ha后面形成链表hc hc=ha; //由指针p指向ha的尾元结点 while(p->next !=NULL) //查找原ha表的最后一个结点 p=p->next; p->next = hb->next; //把hb表的第一个元素及其后面元素接在p指针指向的结点后面 free(hb); }
11、删除单链表中重复的元素
//删除单链表中重复的元素 typedef struct node { elemtype data; struct node *next; }LinkedList ,*LNode; LinkedList DeleteSameElement(LinkedList L) { //L为递增有序的单链表 LNode u; LinkedList p, pre; pre = L->next; //pre指针指向第一个元素结点 p= pre->next; //p指向pre所指结点的后继结点 while(p!=NULL) //如果p指针不为空 if(p->data == pre->data) //p所指结点的值等于pre所指结点的值 { u=p; //用指针u暂存p指针所指向的结点 p=p->next; //p指针后移 free(u); //释放掉u指针所值结点的内存空间 } else{ //p和pre两指针所指向的结点值不相等 pre = p; //pre指针后移 p = p->next; //p指针后移 } }
12、交换单链表中指针p所指结点与其后继结点
//交换单链表中指针p所指结点与其后继结点 typedef struct node { elemtype data; struct node *next; }*LinkList; int exchange(Linklist &head,Linklist p ) { LinkList q=head->next; //q指向第一个元素结点 LinkList pre=head; //pre指向头结点 while(q!=NULL && q!=p) //顺着链表开始查找,一直到q=p { pre=q; q=q->next; } if(p->next ==NULL) //退出循环之后,若p无后继,则交换失败 return 0; else{ q=p->next; pre->next = q; p->next = q->next; q->next = p; } return 1; }
13、设有一个无序单链表
1)找出最小值结点
2)若该数是奇数将与其直接后继结点的数值交换
3)该数值是偶数将直接后继结点删除
/* 设有一个无序单链表 1、找出最小值结点 2、若该数是奇数将与其直接后继结点的数值交换 3、该数值是偶数将直接后继结点删除 */ typedef struct node { elemtype data; struct node *next; }LinkList; void OutputMin(LinkList L) { int temp; LinkList q = L->next; //p指向第一个元素结点 LinkList p= q; while(q) { //找出最小值结点p,并打印p结点数值 if(p->data >q->data) p=q; //如果发现还有比p指针所指结点的值更小的结点,令p指向该结点,否则q后移 q=q->next; } printf("%d",p->data); if(p->next != NULL) //找到了值最小的结点,若该结点有后继结点 { if(p->data % 2 == 1) //如果该最小值是奇数,则与其后继结点交换 { temp=p->data; p->data =p->next->data; p->next->data = temp; } else //如果该最小值是偶数,则删除其后继结点 { q=p->next; p->next = q->next; free(q); } } }