一.帶頭結點的單鏈表
先說一下create()建立的鏈表,採用cycle的方式。
/*************************************************************帶頭結點的單鏈表13-1-1ex3.cpp1.建立單鏈表2.求鏈表長度3.在第i個位置插入元素(種方法)4.刪除指定序號的節點由於本程式是帶前端節點的,所以在刪除函數Del()和插入函數InsertList()中,head均沒有被改變,所以,主函數中,用了Del和InsertList之後均沒有改變head,在PrintList中,還可以繼續把head傳入。如果是這樣的話,這兩個函數完全可以定義成void類型,而不是Node *類型的只要將Create()定義成Node *就行,再在main()中定義一個指標head將head=Create();以後這個head都不會變了。好像帶前端節點鏈表的這些常規操作均不改變Head節點。**************************************************************/#include<stdio.h>#include<stdlib.h>//#include<string.h>//#include<conio.h> typedef struct student{ int data; struct student *next; //struct student *pre;}Node; int GetLength(Node *head){ int n=0; Node *p; p=head->next; while(p!=NULL) { p=p->next; n++; } return n;} Node *InsertList(Node *head, int x, int i) //插入元素方法1{ Node *p, *q, *s; int j=1; p=head; if(i<1 || i>GetLength(head)+1) { exit(1); } s=(Node *)malloc(sizeof(Node)); s->data=x; while(j<=i) { q=p; p=p->next; j++; } s->next=q->next; q->next=s; return head;} void InsertList2(Node *head, int x, int i) //插入元素方法2{ Node *p,*s; int j=1; p=head; if(i<1 || i>GetLength(head)+1) //這塊兒比刪除節點函數多加了一個,因為可以插入到最後一個節點的後面一個節點。但是刪除節點函數不行,只能刪除到最後一個節點 { exit(1); } s=(Node *)malloc(sizeof(Node)); s->data=x; while(j<i) { p=p->next; j++; } s->next=p->next; p->next=s; //return head;}Node *Del(Node *head, int i){ Node *p, *q; int j=1; p=head; if(i<1 || i>GetLength(head)) { exit(1); } while(j<i) { p=p->next; j++; } q=p->next; p->next=q->next; free(q); return head;} Node *create(){ Node *head, *p, *s; int x, cycle=1; head=(Node *)malloc(sizeof(Node)); p=head; //如果換成帶前端節點的鏈表。這裡也不能變,切記,不能變成p=head->next;那就錯了 printf("\nplease input the data:\n"); while(cycle) { //printf("\nplease input the data:\n"); scanf("%d",&x); if(x!=0) { s=(Node *)malloc(sizeof(Node)); s->data=x; //printf("\n %d", s->data); p->next=s; //s->pre=p; p=s; } else { cycle=0; } } p->next=NULL; //head=head->next;//注意,這句是不帶頭結點的單鏈表必須做的,因為按照演算法。輸入的第一個數實際上是賦值給了head->next //printf("\nhead->data:%d\n",head->data); return head;} void PrintList(Node *head) //列印鏈表的所有元素{ Node *p; p=head->next; //1) while(p!=NULL) { printf("%3d", p->data); p=p->next; } printf("\n");} int main(){ Node *p, *q ,*t, *head; head=create(); //p=p->next;//如果是帶前端節點的單鏈表建立,除了少了上面那個函數的末尾的步之外,多了這一步,保證從head的下一個節點輸出鏈表data。 printf("\nnow output the linklist:\n"); PrintList(head); InsertList2(head, 99,3); //q=q->next; printf("\nnow output the new linklist after INSERT:\n"); PrintList(head); /* while(q!=NULL) { printf("%3d",q->data); q=q->next; } printf("\n"); */ Del(head, 3); printf("\nnow output the new linklist after DELETE:\n"); PrintList(head); /* t=t->next; while(t!=NULL); { printf("%3d",t->data); t=t->next; } printf("\n"); */ system("pause"); return 0;}
運行結果如下:
1.輸入為1 2 3 4 5 6。在第三個位置上插入一個數99,然後刪除第3個節點(0為結束控制符)
2.輸入為1 2。在第3個位置上,插入一個數99,然後刪除第三個節點(0為結束控制符)
再說一下create2()建立的鏈表,採用傳統的getchar()方式。
如果用create2()來建立,也很簡單。create2()函數可以直接加在這個程式裡面,另外再改動不多的幾個地方就行,也就是把輸入類型和PrintList中的輸出類型改為char以及%c就行了,途中黃色高亮部分標記的就是要改的。
下面看一下create2()代碼:
Node *create2(){ DataType x; Node *head=(Node *)malloc(sizeof(Node)); Node *s, *r; r=head; while((x=getchar())!='\n') //注意,這個可是getchar()字元輸入的。必須按照順序輸入,不能按空格也不能按斷行符號,不然都會被當做一個字元 { //getchar()把空格也當成一個字元,這點與scanf不同。比如輸入:abcdefg斷行符號。不能這樣輸入:a b c d e f g斷行符號。 s=(Node *)malloc(sizeof(Node)); s->data=x; r->next=s; r=s; //r始終指向尾部節點 } r->next=NULL; return head;}
這麼看來,2種方法都不錯。
還有一點注意就是在插入的時候插入的是字元。別忘了加一個’ ‘。InsertList2(head, 'u',3);
運行結果:
1. 輸入abcdefg
2. 輸入1234567
二.不帶頭結點的單鏈表
說明:基本操作一樣,只不過有些差別。
1. 在Create()中的p->next=NULL;之後,加一句head=head->next;也就是將頭指標head後移。
2. 在PrintList()中,就沒有p=head->next;了直接就p=head;了。
3. 在InsertList()中,需要分3中情況討論:
a) 所插入的位置是首節點(head所指結點);
b) 所插入的位置是中間結點;
c) 所插入的位置是尾節點。
4. 在Del()中,需要分2種情況討論:
a) 所插入位置是首節點(head所指結點);
b) 所插入位置是其他節點(中間節點或者尾節點)。