單/雙 ·連結串列的建立,插入,刪除操作
阿新 • • 發佈:2018-12-17
單鏈表
線性表的鏈式儲存又稱為單鏈表,相比於順序表插入刪除需要移動大量的元素,影響了效率,便引入連結串列,連結串列插入刪除時只需要修改指標。通常用“頭指標”來標識單鏈表,在單鏈表的第一個結點前附加一個結點,稱為頭結點,頭結點無資料域,或者是記錄表長等資訊,頭結點不是必須要有,但是頭指標必須要有,但有了頭結點,連結串列的頭個位置的操作與其他位置的操作無異。注:由於單鏈表的元素是離散的分佈在儲存空間內,所以單鏈表是非隨機儲存的,即不能找到特定的元素,需要從頭遍歷!
結點的結構體型別
typedef struct LNode{ ElemType data; struct LNode *next; } LNode ,*LinkList;
1>.單鏈表建立
- 頭插法建立、 :讀取的資料的順序與生成結點的次序相反;
//頭插法 LinkteList CreatLinket1(LinkteList &head){ //返回一個LinkteList 型別的連結串列,引數是即將建立新建立的連結串列頭(地址) LNode *s; //需要建立結點的指標 int n; //需要建立的結點個數 head = (LinkteList) malloc (sizeof(LNode)); //?建立的頭結點,即代表連結串列的位置,注這是代表LinkteList的指標!因為形參中已經宣告它是指標型別的變數,故不用加*?? head -> next = null; //初始頭結點指標域為空,即為空連結串列 (注:頭結點沒有資料域),頭結點可有可無,頭指標必須有 scanf("%d",&x); //輸入結點的值 while(x != 99){ //此處為建立結點結束的標誌 s = (LNode*) malloc (sizeof(LNode)); //建立新結點,注這是返回LNode*(注意加*)型別的指標! s -> data = x; //把元素放進新建立的結點資料域中 s -> next = head -> next; //每建立一個結點,都重複此操作,即把新結點排在頭結點後面 head -> next = s; //先連後斷!!先兩個指標指向同一個位置,然後頭結點先放手! scanf("%d",&x); //??why? } return head; }
- 尾插法建立`, :讀取的資料的順序與生成結點的次序相同,注意引入另一個尾指標!
//尾插法 LinkteList CreatLinket1(LinkteList &head){ LNode *s,*r = head; // 頭指標不能動,因此找另一個指標變數r向後移動,但必須**初始化** int n; head = (LinkteList) malloc (sizeof(LNode)); //注這是代表LinkteList的指標! head -> next = r; scanf("%d",&x); while(x != 99){ //此處為建立結點結束的標誌 s = (LNode *) malloc (sizeof(LNode)); s -> data = x; r -> next = s; r = s; } r->next = null; // 迴圈結束,尾指標必須為空 return head; } //插入操作 先連後斷,先同時指向被操作結點,然後前驅先放手!!
2>單鏈表插入操作
先連後斷!!先連後斷!!先連後斷!! 順序不能反!
將x的新結點插在單鏈表的第i個位置 通常會採用後插法,故要先找到第(i-1)個結點,即待插入的前驅結點,然後在其後面插入新的結點;
p = GetElem(L,i-1); // 找到待插入結點的前驅
s->next = p->next;
p ->next =s;
3>單鏈表 刪除`
p = GetElem (L ,i-1);
q = p->next; // 令q指向被刪除點;可以理解為q 為指標,而p->next 已知,只是把p->next賦值給q,並不是q 本身就是一個結點
p->next = q->next; //將*q結點從鏈中斷開
free(q); //釋放儲存空間
雙鏈表
雙鏈表有兩個指標prior和next,分別指向前驅和後繼 1>雙鏈表的插入
s->next = p ->next; // 1
p->next->prior = s; // 2
s->prior = p; // 3
p-> next =s; // 4
2>雙鏈表的刪除
p-> next = q -> next ;
q ->next->prior = p;
free(q);