1. 程式人生 > >C 有頭結點連結串列的若干操作

C 有頭結點連結串列的若干操作

比無頭節點的要簡單很多

文章目錄

建立

typedef struct Node {
    int data;
    struct Node * next;
} LNode, * LinkNode;
//建立,絲毫不用理會第一個節點特殊情況 void creatLink(LinkNode * q){ int i; LinkNode e, p1; //頭節點 *q = (LinkNode)malloc(sizeof(LNode)); (*q)->next = NULL; p1 = *q; for (i = 0; i < 10; i++) { //建立新節點 e = (LinkNode)malloc(sizeof(LNode)); e->data = i+1; e->
next = NULL; //把新節點接在連結串列中 p1->next = e; p1 = e; } }

輸出

//輸出,讓過第一個頭節點
void putout(LinkNode q){
    LinkNode p1 = q->next;
    while (p1) {
        printf("%d ", p1->data);
        p1 = p1->next;
    }
    printf("\n");
}

訪問第i個元素

/*訪問第i個元素,並且返回,以引數的方式返回了,這個就是C語言的侷限了,
只能返回一個引數,不像別的能返回個元組什麼的*/
Status findElement(LinkNode q, int i, int *e){ if(i < 1) return ERR; LinkNode p1 = q->next; //很實在從1開始 int n = 1; while (p1) { //這個就是第幾個了 if(n == i) { *e = p1->data; return OK; } p1 = p1->next; n++; } return ERR; }

在i個位置前插入

Status insertElement(LinkNode q, int i, int e){
    if(i < 1 || !q) return ERR;
    //前驅p2,後繼p1
    LinkNode p1 = q->next, p2 = q;
    int n = 1;
    
    while (p1) {
    	//還是先找到第i個位置,以及在第i個位置上的元素和其前驅元素
        if(n == i){
            LinkNode element = (LinkNode)malloc(sizeof(LNode));
            element->data = e;
            element->next = NULL;
            //插入元素
            p2->next = element;
            element->next = p1;
            return OK;
        }
        n++;
        p2 = p1;
        p1 = p1->next;
    }
    return ERR;
}

刪除第i個元素

//刪除第i個元素
Status deleteElement(LinkNode *q, int i, int *e){
    if(i < 1 || !((*q)->next)) return ERR;
   	//還是前驅後繼
    LinkNode p1 = (*q)->next, p2 = (*q);
    int n = 1;
    while (p1) {
     	//找到第i個元素
        if(n == i)
        {
            (*e) = p1->data;
            p2->next = p1->next;
            free(p1);
            return OK;
        }
        n++;
        p2 = p1;
        p1 = p1->next;
    }
    return ERR;
}

頭插

//頭插
Status inserthead(LinkNode *q, int e) {
    if(!(*q)) return ERR;
    LinkNode p1 = *q;
    //從頭開始
    LinkNode element = (LinkNode)malloc(sizeof(LNode));
    element->data = e;
    element->next = p1->next;
    
    p1->next = element;
    return OK;
}

逆置

//逆置
void reverse(LinkNode *q){
    //將頭節點獨立出來,慣例找前驅後繼
    LinkNode p1, p2;
    p1 = (*q)->next;
    (*q)->next = NULL;
    //將元素一次取出來,再按著頭插法,插進去
    while (p1) {
        p2 = p1;
        p1 = p1->next;
        //每次取出來的元素都插在最前面
        p2->next = (*q)->next;
        (*q)->next = p2;
    }
}

尾插

//尾插
Status inserttail(LinkNode *q, int e) {
    if(!(*q)) return ERR;
    LinkNode p1 = *q;
    //p1就是最後一個節點
    while (p1->next) {
        p1 = p1->next;
    }
    
    LinkNode element = (LinkNode)malloc(sizeof(LNode));
    element->data = e;
    element->next = NULL;
 	//接上
 	p1->next = element;
    return OK;
}

排序

//排序
void sort(LinkNode *q){
    LinkNode p1, p2;
    int temp;
    p1 = p2 = (*q)->next;
    
    //選擇
//    for (; p1->next; p1 = p1->next) {
//        for (p2 = p1->next; p2; p2 = p2->next) {
//            if(p1->data > p2->data){
//                temp = p2->data;
//                p2->data = p1->data;
//                p1->data = temp;
//            }
//        }
//    }
    
    //冒泡 每趟只能遍歷到最後,有些許浪費
    for (; p1->next; p1 = p1->next) {
        for (p2 = (*q)->next; p2->next; p2 = p2->next) {
            if(p2->data > p2->next->data){
                temp = p2->data;
                p2->data = p2->next->data;
                p2->next->data = temp;
            }
        }
    }
}

兩個有序連結串列合併在一起,合併在一起的連結串列也要有序

//la和lb遞增,歸併起來lc
LinkNode combine2Links(LinkNode *q1, LinkNode *q2){
    //LinkNode =(* LNode)就是一個指標
    //把兩個連結串列的第一個有數字的結點取出來,
    LinkNode p1 = (*q1)->next;
    LinkNode p2 = (*q2)->next;
    //我現在認為連結串列1就是合併成新的連結串列
    LinkNode L = *q1;
    //第二個連結串列的頭結點於我來說莫得用了
    free(*q2);
    //遍歷p1和p2,哪個小先放哪個
    while (p1 && p2) {
        if(p2->data > p1->data){
            L->next = p1;
            p1 = p1->next;
        }else{
            L->next = p2;
            p2 = p2->next;
        }
        L = L->next;
    }
    //最後剩下哪個全接上去
    if(p2){
        L->next = p2;
    }
    if(p1){
        L->next = p1;
    }
    //返回連結串列1
    return *(q1);
}

找出連結串列中資料最大的節點並返回

LinkNode findmax(LinkNode q){
    LinkNode p1 = q->next, max = NULL;
    //記錄值
    int m = 0;
    while (p1) {
    	//只要發現比它大的,記錄節點也重新整理值
        if(m < p1->data){
            m = p1->data;
            max = p1;
        }
        //往後走
        p1 = p1->next;
    }
    return max;
}

連結串列中最小的節點放在最前面

//將連結串列最小節點移動到連結串列最前面
void insertMinNode(LinkNode *head){
	//遍歷的時候前驅後繼
    LinkNode p1 = (*head)->next;
    LinkNode p = (*head);
    //最小點的前驅後繼
    LinkNode minPreNode = NULL, minNode = NULL;
    //初值
    int min = p1->data;
    //動起來
    while (p1) {
    	//只要發現還有小的就更新節點
        if(min > p1->data){
            min = p1->data;
            minNode = p1;
            minPreNode = p;
        }
        //驅動著往後走
        p = p1;
        p1 = p1->next;
    }
    //遍歷完一次,留下的就是我們要的了,ps.連結串列中最好不要出現兩個一樣小的

	//刪除原有的位置
    minPreNode->next = minNode->next;
    //新增到新的地方
    minNode->next = (*head)->next;
    (*head)->next = minNode;
}

有序連結串列中去除相同值的節點

//有序連結串列中去除相同值的節點
void deleteSimilarNode(LinkNode *head){
	//前驅後繼
    LinkNode prenode = (*head)->next;
    LinkNode node = prenode->next;
    //往下走
    while (node) {
    	//要是相等就走後面的,前頭等著直到走完
        if(prenode->data == node->data){
            prenode->next = node->next;
            free(node);
            node = prenode->next;
        }
        else
        //既然不相等,就都往後移動
        {
            prenode = node;
            node = node->next;
        }
    }
}

升序表裡比x小的有幾個

//升序表裡比x小的有幾個
int lessThanNode(LinkNode q, int x){
    LinkNode p1 = q->next;
    int n = 0;
    while (p1) {
    	//升序,碰見比x大的,那後面肯定都是大的,跳出
        if(p1->data >= x)
            break;
        n++;
        p1 = p1->next;
    }
    return n;
}
//
//  main.c
// 	單鏈表有頭結點
//
//  Created by 赫凱 on 2018/10/23.
//  Copyright © 2018年 赫凱. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERR 0

#define num 0

typedef int Status;

typedef struct Node {
    int data;
    struct Node * next;
} LNode, * LinkNode;

//建立,絲毫不用理會第一個節點特殊情況
void creatLink(LinkNode * q){
    int i;
    LinkNode e, p1;
    
    *q = (LinkNode)malloc(sizeof(LNode));
    (*q)->next = NULL;
    p1 = *q;
    
    for (i = 0; i < num; i++) {
        e = (LinkNode)malloc(sizeof(LNode));
        e->data = i+1;
        e->next = NULL;
        p1->next = e;
        p1 = e;
    }
}
//輸出,讓過第一個頭節點
void putout(LinkNode q){
    LinkNode p1 = q->next;
    while (p1) {
        printf("%d ", p1->data);
        p1 = p1->next;
    }
    printf("\n");
}
//訪問第i個元素
Status findElement(LinkNode q, int i, int *e){
    if(i < 1) return ERR;
    LinkNode p1 = q->next;
    int n = 1;
    while (p1) {
        if(n == i) {
            *e = p1->data;
            return OK;
        }
        p1 = p1->next;
        n++;
    }
    return ERR;
}
//在i個位置前插入
Status insertElement(LinkNode q, int i, int e){
    if(i < 1 || !q) return ERR;
    LinkNode p1 = q->next, p2 = q;
    int n = 1;
    
    while (p1) {
        if(n == i){
            LinkNode element = (LinkNode)malloc(sizeof(LNode));
            element->data = e;
            element->next = NULL;
            
            p2->next = element;
            element->next = p1;
            return OK;
        }
        n++;
        p2 = p1;
        p1 = p1->next;
        
    }
    return ERR;
}
//刪除第i個元素
Status deleteElement(LinkNode *q, int i, int *e){
    if(i < 1 || !((*q)->next)) return ERR;
    
    LinkNode p1 = (*q)->next, p2 = (*q);
    int n = 1;
    while (p1) {
        if(n == i)
        {
            (*e) = p1->data;
            p2->next = p1->next;
            free(p1);
            return OK;
        }
        n++;
        p2 = p1;
        p1 = p1->next;
    }
    return ERR;
}
//頭插
Status inserthead(LinkNode *q, int e) {
    if(!(*q)) return ERR;
    LinkNode p1 = *q;
    
    LinkNode element = (LinkNode)malloc(sizeof(LNode));
    element->data = e;
    element->next = p1->next;
    p1->next = element;
    
    return OK;
}
//尾插
Status inserttail(LinkNode *q, int e) {
    if(!(*q)) return ERR;
    LinkNode p1 = *q;
    
    while (p1->next) {
        p1 = p1->next;
    }
    
    LinkNode element = (LinkNode)malloc(sizeof(LNode));
    element->data = e;
    p1->next = element;
    element->next = NULL;
    
    return OK;
}


int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, World!\n");
    int e, i;
    
    LinkNode head = NULL;
    
    //建立
    creatLink(&head);
    putout(head);
    
    //頭插尾插
    for (i = 0; i < 10; i+=2) {
        if(!inserthead(&head, i)) printf("頭插失敗");
        if(!inserttail(&head, i)) printf("尾插失敗");
    }
    putout(head);
    
    //查詢
    printf("\n查詢\n");
    scanf("%d", &i);
    while (i) {
        if(findElement(head, i, &e)){
            printf("第 %d 位置上為 %d\n", i, e);
        }else{
            printf("輸入引數錯誤!!!\n");
        }
        scanf("%