王道数据结构之单链表——考研复习笔记
单链表的基本操作实现
基本操作
1. 头插和尾插法建表
建表的时候要记得给链表L分配一个新的空间,并让头指针指向NULL;
L = (LinkList)malloc(sizeof(LinkList)); L->next = NULL;
头插和尾插建表函数:
LinkList List_HeadInsert(LinkList &L);//头插 LinkList List_TailInsert(LinkList &L);//尾插
头插实现过程:
s->data = x; s->next=L->next; L->next = s; //r指向的是表头结点
尾插实现过程:
s->data = x; r->next =s; r = s;
2. 前插和后插法插入
前插和后插函数:
bool ListInsert_Next(LinkList &L,int i, int e);//尾插 bool ListInsert_Prior(LinkList &L,int i, int e);//前插
后插的具体实现:
S->data = e; S->next =p->next; p->next=S;
前插的具体实现:
S->next=p->next; S->data=p->data; p->next = S; p->data=e;
3. 结点和位序的查找
结点查找和位序查找的函数:
LNode *GetElem(LinkList L, int i); LNode *LocateElem(LinkList L,int e);
4. 指定结点和位序的删除
删除函数:
bool ListDelete(LinkList &L,int i, int &e): bool DeleteNode(LNode *p);
找到位序删除的具体实现:
LNode *p = GetElem(L,i-1); if(p==NULL||p->next==NULL) return false; LNode *q = p->next; e = q->data; p->next = q->next; free(q); //O(n)
指定结点删除的具体实现:
LNode *q=p->next; p->data = q->data; p->next=q->next; free(q); //O(1)
完整代码如下:
1 #include<iostream> 2 #include<stdlib.h> 3 4 using namespace std; 5 6 typedef struct LNode{ 7 int data; 8 LNode *next; 9 }LNode,*LinkList; 10 11 //LNode *和LinkList是同一个类型 12 //LNode *强调这是一个结点,LinkList强调这是个单链表 13 14 bool InitList(LinkList &L){ 15 L = (LNode *)malloc(sizeof(LNode)); 16 if (L==NULL) return false; //判断内存是否足够 17 L->next = NULL; 18 return true; 19 } 20 21 bool Empty(LinkList L){ 22 return (L->next==NULL); 23 } 24 25 int Length(LinkList L){ 26 27 int len=0; 28 LNode *p=L; 29 while(p->next!=NULL){ 30 p=p->next; 31 len++; 32 } 33 return len; 34 } 35 36 //按位序查找 37 LNode *GetElem(LinkList L, int i){ 38 if(i<0) return NULL; 39 LNode *p = L; 40 int j =0; 41 while(p!=NULL && j<i){ 42 p=p->next; 43 j++; 44 } 45 return p; 46 } 47 48 //按值查找 49 LNode *LocateElem(LinkList L,int e){ 50 LNode *p=L->next; 51 while(p!=NULL &&p->data!=e){ 52 p=p->next; 53 } 54 return p; 55 } 56 57 //后插 58 bool InsertNextNode(LNode *p, int e){ 59 if(p==NULL) return false; //成功规避了越界的情况 60 LNode *S=(LNode *)malloc(sizeof(LNode)); 61 if (S==NULL) return false; 62 S->data = e; 63 S->next =p->next; 64 p->next=S; 65 return true; 66 } 67 68 //前插 69 bool InsertPriorNode(LNode *p,int e){ 70 71 if(p==NULL) return false; 72 LNode *S=(LNode *)malloc(sizeof(LNode)); 73 if(S==NULL) return false; 74 S->next=p->next; 75 S->data=p->data; 76 p->next = S; 77 p->data=e; 78 return true; 79 } 80 81 82 //带头结点情况 83 bool ListInsert_Next(LinkList &L,int i, int e){ 84 if(i<1) return false; 85 /***********************带头结点的情况 86 int j = 1; 87 if(i==1){ 88 LNode *S = (LNode *)malloc(sizeof(LNode)); 89 s->data=e; 90 s->next=L; 91 L=s; 92 return true; 93 } 94 ***************************/ 95 return InsertNextNode(GetElem(L,i-1),e); 96 } 97 98 bool ListInsert_Prior(LinkList &L,int i, int e){ 99 if(i<1) return false; 100 return InsertPriorNode(GetElem(L,i-1),e); 101 } 102 103 104 105 //O(n),从表头开始,找到要删除结点的前一个结点(i-1) 106 bool ListDelete(LinkList &L,int i, int &e){ 107 if(i<1) return false; 108 LNode *p = GetElem(L,i-1); 109 if(p==NULL||p->next==NULL) return false; //越界或要删除的节点位序不存在 110 LNode *q = p->next; 111 e = q->data; 112 p->next = q->next; 113 free(q); 114 return true; 115 } 116 117 //删除指定结点 p O(1) 118 //单链表存在错误,如果p是最后一个结点,只能从表头依次寻找p的前驱 119 bool DeleteNode(LNode *p){ 120 if(p==NULL) return false; 121 LNode *q=p->next; 122 p->data = q->data; 123 p->next=q->next; 124 free(q); 125 return true; 126 } 127 128 LinkList List_TailInsert(LinkList &L){ 129 int x; 130 L=(LinkList)malloc(sizeof(LinkList)); //头结点 131 L->next = NULL; 132 LNode *r = L; 133 while(~scanf("%d",&x)){ 134 LNode *s=(LNode *)malloc(sizeof(LNode)); 135 s->data = x; 136 r->next =s; 137 r = s; //L重新指向新的表尾结点 138 } 139 r->next = NULL; 140 return L; 141 } 142 // 头插法,也可用于链表逆置 143 LinkList List_HeadInsert(LinkList &L){ 144 int x; 145 L = (LinkList)malloc(sizeof(LinkList)); 146 L->next = NULL; 147 while(~scanf("%d",&x)){ 148 LNode *s=(LNode *)malloc(sizeof(LNode)); 149 s->data = x; 150 s->next=L->next; 151 L->next = s; 152 } 153 return L; 154 } 155 156 void Output(LinkList L){ 157 bool f=false; 158 LNode *q = (LNode *)malloc(sizeof(LNode)); 159 q=L->next; 160 while(q!=NULL){ 161 f==false?printf("%d",q->data):printf("->%d",q->data),f=true; 162 q=q->next; 163 } 164 puts(""); 165 } 166 167 //尾插法创建链表 168 void TailIn(LinkList &L){ 169 cout<<"尾插法创建链表:"; 170 L=List_TailInsert(L); 171 Output(L); 172 } 173 174 //头插法创建链表 175 void HeadIn(LinkList &L){ 176 cout<<"头插法创建链表:"; 177 L=List_HeadInsert(L); 178 Output(L); 179 } 180 //插入 181 void Insert(LinkList &L){ 182 cout<<"按位序用后插法插入链表"<<endl;; 183 int x,i; 184 cout<<"输入位序:"; 185 cin>>i; 186 cout<<"输入元素:"; 187 scanf("%d",&x); 188 ListInsert_Next(L,i,x); 189 Output(L); 190 /*cout<<"按位序用前插法插入链表"<<endl; 191 cout<<"输入位序:"; 192 cin>>i; 193 cout<<"输入元素:"; 194 scanf("%d",&x); 195 ListInsert_Prior(L,i,x); 196 Output(L);*/ 197 cout<<"按结点进行后插"<<endl; 198 cout<<"输入结点:"; 199 cin>>x; 200 cout<<"输入插入的值:"; 201 cin>>i; 202 InsertNextNode(LocateElem(L,x),i); 203 Output(L); 204 cout<<"按结点进行前插"<<endl; 205 cout<<"输入结点:"; 206 cin>>x; 207 cout<<"输入插入的值:"; 208 cin>>i; 209 InsertPriorNode(LocateElem(L,x),i); 210 Output(L); 211 } 212 //删除 213 void _(LinkList &L){ 214 int x,i; 215 cout<<"按位序删除一个结点,从头结点开始"<<endl<<"输入位序:"; 216 cin>>i; 217 ListDelete(L,i,x); 218 if(ListDelete)cout<<"删除成功,删除的元素是:"<<x<<endl; 219 else if(!ListDelete) puts("删除失败"); 220 puts("删除一个指定元素结点"); 221 puts("输入要删除的元素:"); 222 cin>>x; 223 DeleteNode(LocateElem(L,x))==true?puts("删除结点成功"):puts("删除结点失败"); 224 Output(L); 225 } 226 227 int main(){ 228 LinkList L; 229 InitList(L); 230 LNode *d = (LNode *)malloc(sizeof(LNode)); 231 TailIn(L); 232 Insert(L); 233 _(L); 234 return 0; 235 }