單鏈表的建立,實現和操作
阿新 • • 發佈:2019-01-27
#include<cstdio> #include<algorithm> #include<stack> #include<iostream> #include<malloc.h> using namespace std; typedef struct LNode { int data; struct LNode *next; } LinkList; //注意,單鏈表頭節點不儲存資料 void InitList(LinkList *&head)//初始化單鏈表 { head=(LinkList*)malloc(sizeof(LinkList)); head->next=NULL; } //下面是兩種建立單鏈表的方法 //其中頭節點為head融合在建立中,因提前建立,所以下方不使用 void CreateListA(LinkList *&head,int a[],int n)//尾插法,依次將元素放在前一個元素後方 { LinkList *r,*s;//建立兩個指標 /*head=(LinkList*)malloc(sizeof(LinkList));//為頭結點分配空間 head->next=NULL;*/ r=head; for(int i=0; i<n; i++) { s=(LinkList*)malloc(sizeof(LinkList)); s->data=a[i]; r->next=s; r=s;//是r不斷更新為所插入的下一個元素,再次進入迴圈 }//通過for迴圈實現尾插法 r->next=NULL; } void CreateListB(LinkList *&head,int a[],int n)//頭插法,邏輯順序與物理順序相反 { LinkList *s; /*head=(LinkList*)malloc(sizeof(LinkList));//分配空間 head->next=NULL;*/ s=head; for(int i=0; i<n; i++) { s=(LinkList*)malloc(sizeof(LinkList)); s->data=a[i]; s->next=head->next; head->next=s;//元素在插入的過程中新元素排在舊元素後面,所以邏輯物理順序相反 } } void DestroyList(LinkList *&head)//銷燬單鏈表 { LinkList *pre=head,*p=head->next;//建立兩個指標,來回使用 while(p!=NULL) { free(pre); pre=p; p=pre->next; }//逐一釋放空間 free(pre);//釋放最後一個 } bool ListEmpty(LinkList *&head)//判斷是否為空表(是否只含有一個頭節點,若是,則為空) { return (head->next==NULL);//如果為空,則返回值為1 } int ListLength(LinkList *head)//計算單鏈表長度 { int n=0; LinkList *p=head; while(p->next!=NULL) { n++; p=p->next; } return n; } void DisplayList(LinkList *head)//輸出線性表各個元素 { LinkList *p=head->next;//由於頭節點不儲存資料,所以從下一個開始 while(p!=NULL) { cout<<p->data<<' '; p=p->next; } cout<<endl; } bool GetElem(LinkList *head,int i,int &e)//求線性表指定位置i的某個元素,將值賦給e,此處先判斷,如成功則賦值輸出 { LinkList *p=head; for(int j=0; j<i&&p!=NULL; j++) { p=p->next; } if(p==NULL)//判斷迴圈中斷的原因,若為p==NULL,則說明超出單鏈表範圍 return false; else { e=p->data; return true; } } int LocateElem(LinkList *head,int e)//找出哪一個位置的元素與e值相等,若不存在,輸出0 { LinkList *p=head->next; int i; for(i=1; p!=NULL&&p->data!=e; i++) { p=p->next; } if(p==NULL)//判斷終止條件 return 0;//代表不存在,遍歷完畢 else return i; } /*下面是單鏈表的插入和刪除操作,可以借用if判斷來得出插入或刪除值。 也可直接呼叫函式*/ bool ListInsert(LinkList *&head,int i,int e)//插入元素在第i個位置插入元素e { LinkList *p=head,*s; for(int j=0; j<i-1&&p!=NULL; j++) { p=p->next; } if(p==NULL) return false; else { s=(LinkList*)malloc(sizeof(LinkList)); s->data=e; s->next=p->next; p->next=s;//畫圖吧,畫圖好理解 return true; } } bool ListDelete(LinkList *&head,int i,int &e)//刪除線性表第i個元素,將刪除元素的值賦給e { LinkList *p=head,*q; for(int j=0; j<i-1&&p!=NULL; j++) { p=p->next; } if(p==NULL) return false; else { q=p->next; if(q==NULL)//判斷p下一個節點是否為空,若為空則不滿足條件 return false; e=q->data;//將要刪除的元素賦給e p->next=q->next; free(q); return true; } } void nixv(LinkList *&head)//就地逆序 { LinkList *p,*r;// p=head->next; head->next=NULL; while(p!=NULL) { r=p->next; p->next=head->next; head->next=p; p=r;//此處關鍵,建議畫圖 } } //以下是函式呼叫測試 int main() { LinkList *head;//初定義 InitList(*&head);//頭節點 cout<<ListEmpty(*&head)<<endl; int n; cout<<"請輸入元素個數n"<<endl; cin>>n; int m; int a[100]; for(int i=0; i<n; i++) { cin>>a[i]; } CreateListA(*&head,a,n);//此處為尾插,頭插用法與此相同 //個人認為可以用不斷插入的方法,這樣可以動態分配記憶體,不用提前開陣列依次填入 DisplayList(*&head);//輸出測試 cout<<"元素個數為"<<ListLength(head)<<endl; int e,z; cout<<"請輸入z,e,代表在第z位置插入元素e"<<endl; cin>>z>>e; ListInsert(*&head,z,e);//插入測試 DisplayList(*&head);//輸出測試 int qq; cout<<"請輸入qq,代表刪除第幾位置的元素"<<endl; cin>>qq; int zz; ListDelete(*&head,qq,zz); DisplayList(*&head);//輸出測試 cout<<"刪除的元素是"<<zz<<endl; cout<<"逆序輸出"<<endl; nixv(*&head); DisplayList(*&head); return 0; }