2、链表

1、创建链表-无头结点

#include<stdio.h>
#include<malloc.h>
#include<assert.h>
typedef int ElemType;

//定义链表 
typedef struct ListNode{
    ElemType data;
    struct ListNode* next;
}ListNode;

typedef ListNode* PList; 

//初始化链表,让链表一开始指向为空 
void initList(PList* head){//此处相当于ListNode** plist [二级指针存储一级指针的地址] 
    *head = NULL;
}
 
//创建链表 尾插法[无虚拟头结点] 
void createListByPushBack(PList* head){
    *head = (ListNode*)malloc(sizeof(ListNode));
//    if(*head == NULL){
//        printf("内存空间不足.\n");
//        return;
//    }
    assert(*head != NULL);
    //处理第一个结点
    (*head)->data = 1;
    (*head)->next = NULL;
    
    ListNode* temp = *head; 
    int i = 2;
    for(i;i <= 3;i++){
        ListNode *p = (ListNode*)malloc(sizeof(ListNode));
        assert(p != NULL);
        p->data = i;
        p->next = NULL;
        
        temp->next = p;
        temp = p;
    }
}

//创建链表 头插法[无虚拟头结点]
void createListByPushFront(PList* head){
    *head = (ListNode*)malloc(sizeof(ListNode));
    assert(*head != NULL);
    //处理第一个结点
    (*head)->data = 1;
    (*head)->next = NULL;
    

    int i = 2;
    for(i;i <= 3;i++){
        ListNode *p = (ListNode*)malloc(sizeof(ListNode));
        assert(p != NULL);
        p->data = i;
        p->next = *head;
        
        *head = p;
    }
}


//打印链表
void showList(ListNode* list){
    while(list != NULL){
        printf("%d ",list->data);
        list = list->next;
    }
} 
int main(){
    PList myList;
    initList(&myList);
    createListByPushFront(&myList);
    showList(myList);
//    printf("\n%d",myList->data);
    return 0;
} 

 

2、创建链表-有头结点

//初始化链表,让链表一开始指向为空 
void initList(PList* head){//此处相当于ListNode** plist [二级指针存储一级指针的地址] 
    *head = (ListNode*)malloc(sizeof(ListNode));//创建虚拟头结点,该节点不储存数据 
    assert(*head != NULL);
    (*head)->next = NULL;
}
 
//创建链表 尾插法[有虚拟头结点] 
void createListByPushBack(PList* head){
    ListNode* p = *head;
    int i = 1;
    for(i;i <= 3;i++){
        p = p->next  = (ListNode*)malloc(sizeof(ListNode));
        assert(p != NULL);
        p->data = i;
        p->next = NULL;    
    }
}

//创建链表 头插法[无虚拟头结点]
void createListByPushFront(PList* head){
    ListNode* temp = *head;
    int i = 1;
    for(i;i <= 10;i++){
        ListNode *p = (ListNode*)malloc(sizeof(ListNode));
        assert(p != NULL);
        p->data = i;
        p->next = temp->next;
        temp->next = p;
    }
}


//展示链表
void showList(ListNode* list){
    ListNode* temp = list->next; 
    while(temp != NULL){
        printf("%d--> ",temp->data);
        temp = temp->next;
    }
} 

 

3、单链表

#include<stdio.h>
#include<malloc.h>
#include<assert.h>

typedef int ElemType;

//单链表节点定义 
typedef struct Node{
    ElemType data;
    struct Node* next;
}Node,*PNode;

//单链表定义 
typedef struct SingleList{
    PNode first;
    PNode last;
    int size;
}List;

//初始化单链表 
void initList(List* list){
    Node* node = (Node*)malloc(sizeof(Node));
    node->next = NULL;//此处最好是置为空 
    list->first = list->last = node;;
    list->size = 0;
}

//尾插法[带有虚拟头结点]
void push_back(List* list,ElemType data){
    Node* pNode = (Node*)malloc(sizeof(Node));
    assert(pNode != NULL);
    pNode->data = data;
    pNode->next = NULL;

    list->last->next = pNode;
    list->last = pNode;
    list->size++; 
}
//头插法[带有虚拟头结点]
void push_front(List* list,ElemType data){
    Node* pNode = (Node*)malloc(sizeof(Node));
    assert(pNode != NULL);
    pNode->data = data;

    //指向第一个节点 
    pNode->next = list->first->next;
    list->first->next = pNode;
    list->size++; 
} 

//打印链表数据
void show_list(List* list){
    PNode p = list->first->next;
    while(p != NULL){
        printf("%d",p->data);
        if(p->next != NULL){
            printf("->");
        }
        p = p->next;
    }
} 

//尾部删除
void pop_back(List* list){
    if(list->size == 0){
        printf("链表长度为0,不可进行删除操作.\n");
        return; 
    }
    PNode p = list->first;
    //p指向最后一个节点的上一个节点 
    while(p->next != list->last){
        p = p->next;
    }
    //释放空间 
    free(list->last);
    //改变单链表的尾指针指向 
    list->last = p;
    list->last->next = NULL;
    list->size--;
}

//头部删除 
void pop_front(List* list){
    if(list->size == 0){
        printf("链表长度为0,不可进行删除操作.\n");
        return; 
    }
    PNode p = list->first->next;
    list->first->next = p->next;
    free(p);
    //注意:如果链表只有一个元素,删除该节点后要修改尾指针!
    if(list->size == 1){
        list->last = list->first; 
    } 
    list->size--;
}

//插入值[默认链表已经从小到大排序好]
void insert_val(List* list,ElemType e){
    Node* pNode = (Node*)malloc(sizeof(Node));
    pNode->data = e;

    PNode p = list->first;
    while(p->next != NULL && p->next->data < e){
        p = p->next; 
    }
    //说明当前插入的位置是最后一个 
    if(p->next == NULL){
        //修改尾指针
        list->last = p; 
    }
    //插入节点 
    pNode->next = p->next;
    p->next = pNode;
    list->size++; 
}

//查找值
Node* find(List list,ElemType e){
    PNode p = list.first->next;
    while(p != NULL){
        if(e == p->data){
            return p;
        }
        p = p->next;
    }
    return NULL;
} 

//单链表长度
int length(List list){
    return list.size; 
} 

//按值删除
void delete_val(List* list,ElemType data){
    Node* node = find(*list,data);
    if(node == NULL){
        printf("删除值不存在链表中.\n");
        return;
    }
    /*
    注意
        这里找到要删除的节点,按之前的思路是要 
        用删除节点的前驱去指向删除节点的后继
        但这里前驱不好寻找,因此更换思路,
        直接用 删除节点的后继 覆盖 要删除节点 
        然后在清楚掉后继节点即可 
    */
    if(node = list->last){
        //删除最后一个节点
        pop_back(list); 
    }else{    
        Node* p = node->next;
        node->data = p->data;
        node->next = p->next;
        free(p);
    }
    list->size--;    
} 

//排序
void sort(List* list){
    if(list->size <= 1){
        return;
    }

    //指向第一个节点 
    Node* p = list->first->next;
    //指向第二个节点 
    Node* q = p->next;

    //断开链表,形成两个链表,后续遍历第二个链表,
    //然后参照按值插入的方式插入数据 
    list->last = p;
    p->next = NULL;

    while(q != NULL){
        p = q;
        q = q->next;
        Node* temp = list->first;
        while(temp->next != NULL && temp->next->data < p->data){
            temp = temp->next;    
        }
        if(temp->next == NULL){
            list->last = p;
        }
        p->next = temp->next;
        temp->next = p;
    }
} 

//逆置链表
void reverse(List* list){
    /*
    逆置思路跟上面差不多
    将链表一分为二,然后将第二个链表元素依次头插到第一个链表即可 
    */ 
    if(list->size <= 0){
        return;
    }
    //指向第一个元素 
    Node* p = list->first->next;
    //指向第二个元素
    Node* q = p->next;
    //链表一分为二 
    list->last = p;
    p->next = NULL; 
    while(q != NULL){
        p = q;
        q = q->next;
        p->next = list->first->next;
        list->first->next = p;

    }
}

//清空链表
void clear(List* list){
    if(list->size == 0){
        return;
    }
    Node* p = list->first->next;
    while(p != NULL){
        list->first->next = p->next;
        free(p);
        p = list->first->next;
    }
    list->last = list->first;
    list->size = 0;
} 

//销毁链表
void destroy(List* list){
    clear(list);
    free(list->first);
    list->first = list->last = NULL;
} 
int main(){
    List list;
    initList(&list);

    int select = 1;
    ElemType item = 0;
    while(select){
        printf("\n");
        printf("***********************************\n");
        printf("* [1] push_back   [2] push_front  *\n");        
        printf("* [3] show_list   [4] pop_back    *\n");
        printf("* [5] pop_front   [6] insert_val  *\n");
        printf("* [7] find        [8] length      *\n");
        printf("* [9] delete_val  [10] sort       *\n");
        printf("* [11] reverse    [12] clear      *\n");
        printf("* [13] destroy    [0] exit_system *\n");
        printf("***********************************\n");
        printf("请选择> ");
        scanf("%d",&select);
        if(!select){
            break;
        }
        PNode p = NULL;
        switch(select){
            case 1:
                printf("请输入要输入的数据(-1结束):>");
                while(scanf("%d",&item),item != -1){
                    push_back(&list,item);
                }
                break;
            case 2:
                printf("请输入要输入的数据(-1结束):>");
                while(scanf("%d",&item),item != -1){
                    push_front(&list,item);
                }
                break;
            case 3:
                show_list(&list);
                break;
            case 4:
                pop_back(&list);
                break;
            case 5:
                pop_front(&list);
                break;
            case 6:
                printf("请输入要插入的数据:>");
                scanf("%d",&item);
                insert_val(&list,item);
                break;
            case 7:

                printf("请输入要查找的数据:>");
                scanf("%d",&item);
                p = find(list,item);
                if(p == NULL){
                    printf("查找的数据不存在.\n");
                }
                break;
            case 8:
                printf("该链表长度为: %d.\n",length(list));
                break;
            case 9:
                printf("请输入要删除的数据:>");
                scanf("%d",&item);
                delete_val(&list,item);
                break;    
            case 10:
                sort(&list);
                break;
            case 11:
                reverse(&list);
                break;
            case 12:
                clear(&list);
                break;
            case 13:
                destroy(&list);
                break; 
        }    
    }
    destroy(&list);
    return 0;
} 

 

4、单链表-代码优化

//---头插尾插优化start--------
//创建节点
Node* create_node(ElemType e){
    Node* pNode = (Node*)malloc(sizeof(Node));
    assert(pNode != NULL);
    pNode->data = e;
    pNode->next = NULL;
    return pNode;
} 
//返回第一个节点 
Node* begin(List* list){
    return list->first->next;
}

//返回最后一个 
Node* end(List* list){
    return list->last->next;
}

//针对pos 的前驱进行插入 
void insert(List* list,Node* pos,ElemType e){
    Node* p = list->first;
    while(p->next != pos){
        p = p->next;
    }
    Node* node = create_node(e);
    
    node->next = p->next;
    p->next = node; 
    if(pos == NULL){
        //插入到链表最后的位置 
        list->last = node;
    }
    list->size++;
}

//尾插法[优化]
void push_back_plus(List* list,ElemType data){
    insert(list,end(list),data);
}

//头插法优化
void push_front_plus(List* list,ElemType data){
    insert(list,begin(list),data);
} 
//-------------end------------- 

 

1、创建链表-无头结点
 
 
2、创建链表-有头结点
 
 
3、单链表
 
c
C
 
 
复制代码
 
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
 
#include<stdio.h>
 
printf("\n");
printf("***********************************\n");
printf("* [1] push_back [2] push_front *\n");
printf("* [3] show_list [4] pop_back *\n");
printf("* [5] pop_front [6] insert_val *\n");
printf("* [7] find [8] length *\n");
printf("* [9] delete_val [10] sort *\n");
printf("* [11] reverse [12] clear *\n");
printf("* [13] destroy [0] exit_system *\n");
printf("***********************************\n");
printf("请选择> ");
scanf("%d",&select);
if(!select){
break;
}
PNode p = NULL;
switch(select){
case 1:
printf("请输入要输入的数据(-1结束):>");
while(scanf("%d",&item),item != -1){
push_back(&list,item);
}
break;
case 2:
printf("请输入要输入的数据(-1结束):>");
while(scanf("%d",&item),item != -1){
push_front(&list,item);
}
break;
case 3:
show_list(&list);
break;
case 4:
pop_back(&list);
break;
case 5:
pop_front(&list);
break;
case 6:
printf("请输入要插入的数据:>");
scanf("%d",&item);
insert_val(&list,item);
break;
case 7:
 
printf("请输入要查找的数据:>");
scanf("%d",&item);
p = find(list,item);
if(p == NULL){
printf("查找的数据不存在.\n");
}
break;
case 8:
printf("该链表长度为: %d.\n",length(list));
break;
case 9:
printf("请输入要删除的数据:>");
scanf("%d",&item);
delete_val(&list,item);
break;
case 10:
sort(&list);
break;
case 11:
reverse(&list);
break;
case 12:
clear(&list);
break;
case 13:
destroy(&list);
break;
}
}
destroy(&list);
return 0;
}
 
 
 
4、单链表-代码优化
 
单链表代码优化
C
 
 
复制代码
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 
//---头插尾插优化start--------
//创建节点
Node* create_node(ElemType e){
Node* pNode = (Node*)malloc(sizeof(Node));
assert(pNode != NULL);
pNode->data = e;
pNode->next = NULL;
return pNode;
}
//返回第一个节点
Node* begin(List* list){
return list->first->next;
}
 
//返回最后一个
Node* end(List* list){
return list->last->next;
}
 
//针对pos 的前驱进行插入
void insert(List* list,Node* pos,ElemType e){
Node* p = list->first;
while(p->next != pos){
p = p->next;
}
Node* node = create_node(e);
 
node->next = p->next;
p->next = node;
if(pos == NULL){
//插入到链表最后的位置
list->last = node;
}
list->size++;
}
 
//尾插法[优化]
void push_back_plus(List* list,ElemType data){
insert(list,end(list),data);
}
 
//头插法优化
void push_front_plus(List* list,ElemType data){
insert(list,begin(list),data);
}
//-------------end-------------
posted @ 2024-09-13 11:16  颜欢兮  阅读(19)  评论(0)    收藏  举报