數據結構學習筆記二 線性表的鏈式存儲結構1

單鏈表中鏈表中結點的結構:分爲數據域和指針域兩個部分,指針域指示下一個結點的地址
首先設一個head指針指向開始結點,終端結點的指針域爲NULL。由於單鏈表的頭指針是唯一的,
所以可以用作鏈表的名字。

用到的幾個函數:
①:void * malloc(unsigned int size);//在內存的動態存儲區中分配一個長度爲size的連續空間
②:void * calloc(unsigned n,unsigned size); //分配長度爲n長度的空間
③:void free(void * p) // 釋放p所指向的內存區

建立單鏈表的方法(將字符放入鏈表中)

一:頭插法建表
在一個空表中,生成新的結點,將讀入的數據放到新的結點數據域中,然後將新的結點插入到鏈表的表頭位置
缺點:輸入的順序與鏈表的順序相反

二:尾插入法建表
鏈表結構中有一個尾指針,並始終指向尾結點。操作方法是在空表中,將新的結點存放到頭指針中,其餘的結點放在其前驅結點的指針域中。
缺點:需要對頭結點單獨處理。

三。帶頭結點的尾插法(常規建表法)


開始的結點的位置存放在頭結點的指針域中,無論鏈表是否爲空,其頭指針是指向頭結點的非空指針。
一般在頭結點的數據域中存放長度等信息

下面是示例代碼

#include "stdlib.h" #include "stdio.h" typedef char DataType; typedef struct node { DataType data; //鏈表的數據域 struct node *next; //鏈表的指針域 } ListNode; typedef ListNode *LinkList; void Error(char * message) { fprintf(stderr,"Error:%s\n",message); exit(1); } // 頭插法建表--生成鏈表節點的次序和輸入相反 LinkList CreateListF(void) { char ch; LinkList head; //頭指針 ListNode *s; //工作指針 head = NULL; //鏈表開始爲空 ch = getchar(); while(ch!='\n') { s=(LinkList)malloc(sizeof(ListNode));//生成新的節點 s->data=ch; s->next=head; //將節點*s插到單鏈表head的頭上 head = s; //重新定義頭指針 ch=getchar(); } return head; } // 尾插法建表 LinkList CreateListR(void) { char ch; LinkList head; ListNode *s, *r; //r爲尾指針 head=NULL; r=NULL; // 鏈表初始值爲空 ch = getchar(); while(ch!='\n') { s=(LinkList)malloc(sizeof(ListNode)); //生成新的節點 s->data=ch; if(head==NULL) { head=s; //開始的節點的位置存在head中 }else{ r->next=s; // 其餘的節點在其前驅節點的指針域中。 } r=s; //尾指針指向新的表尾 ch = getchar(); } if(r!=NULL) { r->next=NULL; //將尾節點置爲空 } return head; } // 有頭結點的單鏈表(通常用法) LinkList CreateListR1(void) { char ch; LinkList head = (LinkList)malloc(sizeof(ListNode));//生成一個頭結點 ListNode *s,*r; r=head; //尾結點初始值指向頭結點 while((ch=getchar())!='\n') { s=(LinkList)malloc(sizeof(ListNode)); //生成一個新結點 if(s==NULL) printf("Error!"); s->data=ch; //新結點數據域賦值 r->next=s; //尾結點指針域((*r).next)指向新結點 r=s; //尾指針指向新結點 } r->next=NULL; return head; } // 按序號查找 ListNode * GetNode(LinkList head,int i) { int j; ListNode *p; p=head;j=0; while(p->next&&j<i) { p=p->next; j++; } if(i==j) { return p; }else { return NULL; } } // 按值查找 ListNode * LocateNode(LinkList head,DataType val) { ListNode *p=head->next; while(p&&p->data!=val) { p=p->next; } return p; } // 插入運算(將x插入到第i個結點上) void InsertList(LinkList head,DataType x,int i) { ListNode *s; // 工作指針 ListNode *p; p=GetNode(head,i-1); // 找到第i-1個結點 if(p==NULL) { Error("position error"); } s=(LinkList)malloc(sizeof(ListNode)); //生成一個新結點 s->data =x; // 將x賦值於新結點的數據域 s->next = p->next; // 新結點的指針域指向原來的指針域 p->next = s; // 原來的指針域指向新的結點 } // 刪除運算(刪除第i個結點) void DeleteList(LinkList head,int i) { ListNode *p,*r; p=GetNode(head,i-1); // 找到第i-1個結點 if(p==NULL||p->next==NULL) { Error("position error"); } r=p->next; // r指向要刪除的結點 p->next=r->next; // 第i-1個結點的指針域指向要刪除結點的後繼結點 free(r); // 釋放刪除的結點 } // 打印鏈表 void PrintAll(LinkList head) { ListNode *p; p=head; printf("鏈表元素一覽:\n"); while(p!=NULL) { printf("%c\n",p->data); p=p->next; } } main() { //ListNode *L1=CreateListF(); //ListNode *L2 = CreateListR(); ListNode *L3 = CreateListR1(); ListNode *p; int i=2; //PrintAll(L1); //PrintAll(L2); PrintAll(L3); p=GetNode(L3,i); printf("第%d個元素爲:%c\n",i,p->data); printf("添加一個結點後:"); InsertList(L3,'P',3); PrintAll(L3); printf("刪除後:"); DeleteList(L3,3); PrintAll(L3); }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章