头插法和尾插法建立链表并合并
线性表
线性表有两种表示方法,顺序表示和链式表示。
顺序表示:数组
优:(1)用数组存储数据元素,操作方法简单,容易实现
(2)无须为表示结点间的逻辑关系而增加额外的存储开销
(3)存储密度高
(4)顺序表可按元素位序随机存取结点
缺:(1)做插入、删除操作时,需大量移动数据元素,效率非常低
(2)要占用连续的存储空间,存储分配只能预先进行。分配过大,会导致空间浪费;分配过小将会造成数据溢出。
链式表示:链表
其特点为与顺序表相反 链表不用事先估计存储空间的大小,但其存储密度较低(存储密度:指一个结点中数据元素所占的存储单元数和整个结点所占的存储单元之比,顺序表的存储密度为1,链式存储密度小于1)
链表的插入有两种方式:头插法和尾插法
头插法:在头结点(为了操作方便,在单链表的第一个结点之前附加一个结点,称为头结点。头结点的数据域可以存储数据标题、表长等信息,也可以不存储任何信息,其指针域存储第一个结点的首地址)头结点之后插入数据,其特点是读入的数据顺序与线性表的逻辑顺序正好相反
oid CreateList_b(LinkList Lb) //头插法 { int s_f,flag=1; Node *p; p=Lb; printf("Please enter Lb data and enter 0 over:\n") ; while(flag) { scanf("%d",&s_f); if(s_f!=0) { p=(LinkList)malloc(len); p->data=s_f; p->next=Lb->next; Lb->next=p; } else flag=0; } }
尾插法:将每次插入的新结点放在链表的尾部(链表中结点的顺序与输入的顺序一致)
void CreateList_a(LinkList La) //尾插法 { int s_f,flag=1; Node *p1,*p2; p1=La; printf("Please enter La data and enter 0 over:\n") ; while(flag) { scanf("%d",&s_f); if(s_f!=0) { p2=(LinkList)malloc(len); p2->data=s_f; p1->next=p2; p1=p2; } else { flag=0; p1->next=NULL; } } }
链表合并
利用现有的LA和LB中的空间结点来合并LC,可通过更改结点的next域来重建新链表LC,为保证新链表依然有序递增,用尾插法建立,只是新链表的建立中不用malloc,只要从LA和LB中选择合适的点插入即可
LinkList MergeLinkList(LinkList La,LinkList Lb) { Node *pa,*pb,*r; pa=La->next; pb=Lb->next; Lc=La; Lc->next=NULL; r=Lc; while(pa!=NULL&&pb!=NULL) { if(pa->data<=pb->data) { r->next=pa; r=pa; //r始终指向Lc的表尾 pa=pa->next; } else { r->next=pb; r=pb; pb=pb->next; } if(pa) r->next=pa; else r->next=pb; free(Lb); } return Lc; }
完整代码:
#include<stdio.h> #include<stdlib.h> #define len sizeof(Node) typedef struct Node { int data; struct Node *next; }Node,*LinkList; LinkList La,Lb,Lc; void InitList_a(LinkList* La) { *La=(LinkList)malloc(len); (*La)->next=NULL; } void InitList_b(LinkList* Lb) { *Lb=(LinkList)malloc(len); (*Lb)->next=NULL; } void CreateList_a(LinkList La) //尾插法 { int s_f,flag=1; Node *p1,*p2; p1=La; printf("Please enter La data and enter 0 over:\n") ; while(flag) { scanf("%d",&s_f); if(s_f!=0) { p2=(LinkList)malloc(len); p2->data=s_f; p1->next=p2; p1=p2; } else { flag=0; p1->next=NULL; } } } void CreateList_b(LinkList Lb) //头插法 { int s_f,flag=1; Node *p; p=Lb; printf("Please enter Lb data and enter 0 over:\n") ; while(flag) { scanf("%d",&s_f); if(s_f!=0) { p=(LinkList)malloc(len); p->data=s_f; p->next=Lb->next; Lb->next=p; } else flag=0; } } void print_a(LinkList La) { Node *p; printf("La data is:\n"); for(p=La->next;p!=NULL;p=p->next) printf("%d\n",p->data); } void print_b(LinkList Lb) { Node *p; printf("Lb data is:\n"); for(p=Lb->next;p!=NULL;p=p->next) printf("%d\n",p->data); } LinkList MergeLinkList(LinkList La,LinkList Lb) { Node *pa,*pb,*r; pa=La->next; pb=Lb->next; Lc=La; Lc->next=NULL; r=Lc; while(pa!=NULL&&pb!=NULL) { if(pa->data<=pb->data) { r->next=pa; r=pa; //r始终指向Lc的表尾 pa=pa->next; } else { r->next=pb; r=pb; pb=pb->next; } if(pa) r->next=pa; else r->next=pb; free(Lb); } return Lc; } void print_c(LinkList Lc) { Node *p; printf("Lc data is:\n"); for(p=Lc->next;p!=NULL;p=p->next) printf("%d\n",p->data); } int main() { LinkList La,Lb,Lc; InitList_a(&La); InitList_b(&Lb); CreateList_a(La); CreateList_b(Lb); print_a(La); print_b(Lb); Lc=MergeLinkList(La,Lb); print_c(Lc); free(La); return 0; }