線性表
線性表有兩種表示方法,順序表示和鏈式表示。
順序表示:數組
優:(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; }