1 //当只需要做查找操作的时候 最好的是用顺序表O(1) 
  2 //经常需要做插入和删除的时候 用链表,当然如果这个位置在表末尾,用顺序表也行
  3 //当经常删除和插入的位置在表头或者中间的时候,顺序表要挪很多次
  4 //空间上:链表要比顺序表消耗大 因为多了指针域 
  5  /*C++中用stl list就能用链表了 头文件是<list> 
  6     JAVA中用链表就是引入LinkedList 和ArrayList的使用方法一样 
  7  */
  8  
  9 /*
 10 带头指针:第一个头结点就存放数据,但是有head pointer指向这个节点
 11 带头结点:第一个头结点不存放数据,只是用来索引链表的起始位置 
 12 相比较:
 13         head node
 14             |
 15         [    ] -> [    ] -> [    ] -> ....    
 16             
 17         带头结点的比带头指针的要多耗一个空间
 18         
 19         
 20         head pointer
 21             |
 22         ??????     -> [ ] -> [ ] -> [ ]
 23         带头指针在遍历过程中会(可以)发生变化
 24         而带头结点的不能改变指针域,只能改变头结点的指针域 
 25 */
 26 #include<cstdio>
 27 #include<iostream>
 28 #include<cstdlib>
 29 
 30 using namespace std;
 31 
 32 struct Node{
 33     int data;
 34     struct Node* next;
 35 };
 36 
 37 typedef struct Node* LList;
 38 
 39 void init(struct Node **phead){
 40     *phead = NULL;
 41 }
 42 
 43 int getLength(struct Node* head){
 44     int len = 0;
 45     while(head != NULL){
 46         len ++;
 47         head = head->next;//并没有改变头指针 只是修改了head这个局部变量 
 48     }
 49     
 50     return len;
 51 }
 52 
 53 void printList(struct Node* head){
 54     while(head!=NULL){
 55         printf("%d, ",head->data);
 56         head = head->next;//并没有改变头指针 只是修改了head这个局部变量 
 57     }
 58     printf("n");
 59 }
 60 
 61 struct Node* createNode(int x){
 62     struct Node* t;
 63     //这里应该要加入一个判断剩余空间是否足够malloc 
 64     t = (struct Node*)malloc(sizeof(struct Node));
 65     t->next = NULL;
 66     t->data = x;
 67     return t;
 68 }
 69 
 70 //因为查找第k-1个点在insert和remove中都要用到
 71 //我们在编程中应该尽量不要去复制代码 而是封装成函数
 72 //尽管函数名叫findK,但是我们找的是第k-1个,所以函数传值传的是k-1 
 73 struct Node * findKth(struct Node* head, int k){
 74     int count = 1;
 75     struct Node* p;
 76     p = head;
 77     while(p != NULL && count < k){
 78         p = p->next;
 79         count++;
 80     }
 81     //p可能为空 但是无所谓 下面调用这个函数的地方也有判断语句 
 82     return p;
 83 } 
 84 
 85 
 86 //** 指针的指针,存的是指针的地址 
 87 bool insert(struct Node** phead, int k, int x){
 88     if(k < 1){
 89         return false;
 90     }
 91     //在第一个点插入,要把头指针指向这个点
 92     else if(k == 1){
 93         struct Node *t;
 94         //注意createNode后,t->next = NULL
 95         //假如这个链表原来不是个空表的话,原来的数据都会丢失
 96         t = createNode(x);
 97         //要把原先的点的next赋值给t才行 
 98         t->next = *phead;
 99         *phead = t;
100         return true;
101     }
102     
103     //在第一个点后面插入的情况 
104     //一个个去遍历找到k-1的位置 如果k-1不存在那就没法插入了
105     //例如1 2 3 4,插在6是插不了,插在5就可以
106     struct Node * p;//存k-1的位置
107     /*
108     int count = 1;//用来计数
109     p = *phead; 
110     //当循环判断条件里面的范围不确定的时候,先试着运行一下等下再修改也行 
111     while(p!=NULL && count < k - 1){
112         p = p->next;
113         count ++; 
114     } 
115     封装成了findKth 
116     */
117     //尽管函数名叫findK,但是我们找的是第k-1个,所以函数传值传的是k-1 
118     p = findKth(*phead, k - 1);
119     
120     if(p){
121         struct Node* t;
122         //因为(struct Node*)malloc(sizeof(struct Node));要在很多地方用
123         //干脆就搞成一个函数算了 
124         t = createNode(x); 
125         t->next = p->next;
126         p->next = t;
127         return true;
128     }
129     else{// 1 2 3 4你要插入6,p会指向前一个,就是空的,就插不进去 
130         return false;
131     }
132 }
133 
134 bool removeNode(struct Node** phead, int k, int *px){
135     //区分第一个节点和后面的节点
136     if(k < 0){
137         return false; 
138     }    
139     if(k == 1){
140         if(*phead != NULL){
141             *px = (*phead)->data;
142             *phead = (*phead)->next;
143             return true;
144         }
145         //*phead为空的时候这个表是个空表 
146         else return false;
147         
148     }
149     else{
150         struct Node *p;
151         p = findKth(*phead, k - 1);
152         if(p == NULL || p->next == NULL){
153             //要删除第k个,当没有第k-1位置,或者k-1往下是空(就没有第k个,也是错) 
154             return false;
155         }
156         struct Node* t;
157         t = p->next;
158         p->next = t->next;
159         *px = t->data;
160         free(t);
161         return true;
162     }
163 }
164 
165 int main(){
166     LList head;//头指针
167     //初始化 创建空链表
168     init(&head);    
169     //遍历(打印 求表长)
170     int k =    getLength(head); 
171     //printf("%dn",k); 测试 
172     printList(head);
173     //int falg = insert(&head, 1, 11); 测试插入 
174     insert(&head, 1, 11);//head表示哪个表,因为头指针可能会变,所以传head的地址;位置;元素数据 
175     insert(&head, 1, 22);
176     insert(&head, 2, 33);
177     insert(&head, 4, 44);
178     insert(&head, 6, 55);
179     printList(head);
180     int x;//传入x的地址,用x来获取删除的点的数值 
181     removeNode(&head, 1, &x);//删除第一个点的时候会改变头指针,所以传入地址  
182     //printf("%dn",x);
183     printList(head);
184     return 0;
185 }

 

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/GDUFdebuger/p/15024428.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!