1. 程式人生 > >c語言實現單向迴圈連結串列

c語言實現單向迴圈連結串列

//單迴圈連結串列, 在單鏈表的基礎上, 每建立一個節點,讓其後繼預設指向head
//最終保證最後一個節點的後繼指向Head則構成單迴圈連結串列

//不帶頭節點判空: head == NULL
//帶頭節點判空:  head->next == head; 為空

//與單鏈表程式碼的區別: 每次迴圈的跳出條件改變,尾插發生改變 
//只要程式中插入節點是頭節點, 則必須更新尾節點的指向

//刪除頭節點, 更新尾節點指向, 刪除尾巴節點, 更新前一個節點的指向

建議讀者還是自己從單鏈表到迴圈連結串列手動實現一遍, 迴圈連結串列的道理很簡單

但是其中的許多細節,尤其是插入,刪除,以及頭結點,尾節點的處理等等存在一些難以注意到的問題,還是敲一遍來的實在!

單向迴圈連結串列選擇了單鏈表中的部分功能實現,讀者也可兩者對比來看

單鏈表各種功能的實現:http://blog.csdn.net/hkhl_235/article/details/78196865

主要功能:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h> //包含sleep的標頭檔案,用來使程式暫停(linux)windows下可用用#include<windows.h> Sleep(2000);
typedef struct node
{
    int no;
    int age;
    char sex[5];
    char name[20];
    struct node *next;
}Node;

void Print(Node *head);     //列印
void CreateNode(Node *head, Node **p, int no, int age, char *sex, char *name);//建立節點
void Add(Node **head, int no, int age, char *sex, char *name);    //新增節點
Node *FindNode(Node *head, int no);         //根據學號找節點, 沒有返回NULL
Node *PrvNode(Node *head, Node *find);      //找到前驅節點
void SerchNode(Node *head, int no);         //按學號查詢資訊
void Insert(Node **head);                   //按學號大小有序插入
void HeadInsert(Node **head, int sid);      //某個節點前插入(包括頭插)
void BackInsert(Node **head, int sid);      //某個節點後插入(包括尾插)
void DeleteNode(Node **head, int no);       //刪除學號為no的節點
void FreeAll(Node **head);                  //銷燬連結串列
int GetToatalNode(Node *head);              //獲取節點總數

函式實現部分:
void Print(Node *head)
{
    Node *first = head;
    if(head != NULL)
    {
        printf("學號   年齡   性別   姓名    下一個指向\n");
        while(head != NULL)
        {
            printf("%d    %d     %s     %s   %p\n", head->no, head->age, head->sex, head->name, head->next);
            head = head->next;
            if(head == first)
            {
                //sleep(2); 是程式掛起兩秒  //註釋break可以迴圈列印
                break ;
            }
        }
    }
    else
    {
        printf("空連結串列哦\n");
    }
}

void CreateNode(Node *head, Node **p, int no, int age, char *sex, char *name)
{
    *p = (Node *)malloc(sizeof(Node));
    if(*p != NULL)
    {
        (*p)->no = no;
        (*p)->age = age;
        strcpy((*p)->sex, sex);
        strcpy((*p)->name, name);
        (*p)->next = head;
    }
    else
    {
        printf("建立節點失敗\n");
    }
}

//為空建立新增節點,, 不為空尾部插入...
void Add(Node **head, int no, int age, char *sex, char *name)
{
    Node *h = *head;
    Node *p;
    if(*head == NULL)
    {
        CreateNode(*head, &p, no, age, sex, name);
        *head = p;           //只有第一次賦值,將頭指標的內容更改
        p->next = *head;     //第一個節點建立的時候, CreareNode建立節點p的p->next 等於head ,但是此時head是NULL, 所以這裡要再次賦值 .不然執行到A會報錯
    }
    else
    {
        CreateNode(*head, &p, no, age, sex, name);
        while(h->next != *head)   //while迴圈條件是(*->next)都將發生改變
        {
            h = h->next;     //A, 如果head是NULL, 那麼這裡訪問非法記憶體
        }
        h->next = p;
    }
}

//根據學號找到其節點
//沒找到返回NULL
Node *FindNode(Node *head, int no)
{
    int flag = 0;
    Node *first = head;
    while(head)
    {
        if(head->no == no)
        {
            flag = 1;
            break;
        }
        head = head->next;
        if(head == first)
        {
            break;
        }
    }
    if(flag == 0)
    {
        return NULL;
    }
    return head;
}

//找到前驅節點
Node *PrvNode(Node *head, Node *find)
{
    Node *first = head;
    while(head)
    {
        if(find == head)    //如果找頭節點前一個節點 返回頭節點
        {
            break;
        }
        if(head->next == find)
        {
            break;
        }
        head = head->next;
        if(head == first)
        {
            break;
        }
    }
    return head;
}

//有序插入  按學號由小到大
void Insert(Node **head)
{
    Node *first = *head;
    printf("請輸入要插入的資訊:\n");
    int no;
    float age;
    char sex[5];
    char name[10];
    scanf("%d%f%s%s", &no, &age, sex, name);
    Node *q;
    CreateNode(*head, &q, no, age, sex, name);
    
    Node *p1 = *head;
    Node *p2;

    int flag = 0; 
    while(p1->no <= no) //先判斷是否為NULL
    {
        p2 = p1;
        p1 = p1->next;
        if(p1 == *head)
        {
            flag = 1; 
            break;
        }
    }
    
    if(p1 == *head && flag != 1)              //頭部插入
    {
        q->next = p1;
        *(head) = q;

        //尾節點要重新指向新的頭節點
        for(; p1->next != first; p1 = p1->next);
        p1->next = *head;
    }
    else if(p1 == *head && flag == 1)         //尾部插入 
    {
        p2->next = q;   
        q->next = *head;
    }
    else                                      //中間插入
    {
        q->next = p2->next;
        p2->next = q;
    }
}

void HeadInsert(Node **head, int sid)      //某個節點前插入(包括頭插)
{
    Node *first = *head;
    printf("請輸入要插入的資訊:\n");
    int no;
    float age;
    char sex[5];
    char name[10];
    scanf("%d%f%s%s", &no, &age, sex, name);
    Node *q;
    CreateNode(*head, &q, no, age, sex, name);
    
    Node *p1 = FindNode(*head, sid);
    Node *p2 = PrvNode(*head, p1);

    if(p1 == *head)             //頭部插入
    {
        q->next = p1;
        *(head) = q;

        //尾節點要重新指向新的頭節點
        for(; p1->next != first; p1 = p1->next);
        p1->next = *head;
    }
    else                        //中間插入
    {
        q->next = p2->next;
        p2->next = q;
    }
}

void BackInsert(Node **head, int sid)       //某個節點後插入(包括尾插)
{
    printf("請輸入要插入的資訊:\n");
    int no;
    float age;
    char sex[5];
    char name[10];
    scanf("%d%f%s%s", &no, &age, sex, name);
    Node *q;
    CreateNode(*head, &q, no, age, sex, name);
    
    Node *p1 = FindNode(*head, sid);
    Node *p2 = p1->next;

    if(p1->next == *head)        //尾部插入
    {
        p1->next = q;
        q->next = *head;
    }
    else                         //中間插入
    {
        q->next = p1->next;
        p1->next = q;
    }
}

//學號為no的成員刪除
void DeleteNode(Node **head, int no)
{
    Node *first = *head;
    Node *p1, *p2;
    p1 = p2 = NULL;

    p1 = *head;
    while(p1)   //遍歷節點 找到節點
    {
        if(p1->no == no)
        {
            break;
            //如果刪除的是最後一個, 此時p1跳出, p1並不是NULL
            //所以刪除不用判斷尾節點
        }
        p2 = p1;
        p1 = p1->next;
        if(p1 == *head)
        {
            break;
        }
    }

    if(p1 == *head)          //刪除頭節點
    {
        (*head) = p1->next;  //跳過頭節點

        //尾節點要重新指向新的頭節點
        Node *p = p1;
        for(; p->next != first; p = p->next);
        p->next = *head;

        free(p1);            //釋放頭節點
    }
    else                     //刪除其他節點
    {
        p2->next = p1->next;
        free(p1);
    }
}

void SerchNode(Node *head, int no)            //按學號查詢資訊
{
    Node *sr = FindNode(head, no);
    if(sr != NULL)
    {
        printf("%d    %d     %s     %s   %p\n", sr->no, sr->age, sr->sex, sr->name, sr->next);
    }
    else
    {
        printf("查無此人\n");
    }
}

//刪除所有節點
//最後刪除頭節點
void FreeAll(Node **head)
{
    Node *p1 = *head;
    Node *p2 = NULL;
    Node *q = NULL;
    while(p1->next == *head)
    {
        p2 = p1->next;
        p1->next = p2->next;
        free(p2);
    }
    free(*head);
    *head = NULL;
}

int GetToatalNode(Node *head)              //獲取節點總數
{
    int num = 0;
    Node *first = head;
    if(head != NULL)
    {
        while(head != NULL)
        {
            num++;
            head = head->next;
            if(head == first)
            {
                break;
            }
        }
    }
    return num;
}



下面是測試程式碼:

int main()
{
    Node *head = NULL;

    Add(&head, 1002, 17, "男", "張2");
    Add(&head, 1001, 15, "男", "張1");
    Add(&head, 1003, 12, "男", "張3");
    Add(&head, 1004, 21, "男", "張4");
    Add(&head, 1005, 22, "女", "張5");
    Print(head);
    

    printf("刪除學號為1005的的連結串列:\n");
    DeleteNode(&head, 1002);
    Print(head);

    printf("\n統計結點總數為: %d\n\n", GetToatalNode(head));

    printf("插入資訊後的連結串列(指定節點插入):\n");
    printf("(前插)輸入學號, 年齡, 性別, 姓名:\n");
    HeadInsert(&head, 1002);
    Print(head);
    printf("(後插)輸入學號, 年齡, 性別, 姓名:\n");
    BackInsert(&head, 1004);
    Print(head);


    printf("插入資訊後的連結串列(有序插入):\n");
    printf("輸入學號, 年齡, 性別, 姓名:");
    Insert(&head);
    Print(head);

    printf("銷燬後的連結串列:\n");
    FreeAll(&head);
    Print(head);

    return 0;
}

如有問題,歡迎指出,共同進步! 單鏈表各種功能的實現:http://blog.csdn.net/hkhl_235/article/details/78196865

相關推薦

c語言實現單向迴圈連結串列

//單迴圈連結串列, 在單鏈表的基礎上, 每建立一個節點,讓其後繼預設指向head //最終保證最後一個節點的後繼指向Head則構成單迴圈連結串列//不帶頭節點判空: head == NULL //帶頭節點判空:  head->next == head; 為空 //與

c語言實現雙向迴圈連結串列

此次工程還是使用了3個原始檔list.h(標頭檔案原始碼),main.c(實現介面的具體程式碼),list.c(單鏈表邏輯) list.h #pragma once #include<stdio.h> #include<stdlib.h> #include

資料結構之鏈式表的實現--單向迴圈連結串列(C語言)

 學習參考: 嚴蔚敏: 《資料結構-C語言版》 單向迴圈連結串列的基本操作 單向迴圈連結串列的建立 單向迴圈連結串列新增結點(頭插法) 單向迴圈連結串列新增結點(尾插法) 單向迴圈連結串列

C語言_雙向迴圈連結串列的基本操作

目錄: 1、初始化 2、頭部插入 3、頭部刪除 4、尾部插入 5、尾部刪除 6、列印連結串列 7、任意位置插入 8、查詢值為data的節點 9、指定位置刪除 10、銷燬連結串列 ###1、初始化: 建立一個節點,給節點賦值為0;因為是迴圈連結串列,所以讓它的_pNext

用Python實現單向迴圈連結串列

直接看程式碼,有詳細註解 class Node(object): """節點""" def __init__(self, elem): self.elem = elem self.next = None class SingleCycl

C語言實現在一個連結串列刪除指定的一個或多個元素

#include<stdio.h> #include<stdlib.h> typedef struct node{ int data; struct node *next; }LinkList; //建立一個連結串列  LinkL

C語言實現兩個連結串列查集

#include<stdio.h> #include<stdlib.h> typedef struct node{ int data; struct node *next; }LinkList; //建立連結串列 LinkLis

演算法精解(二):C語言描述(迴圈連結串列

迴圈連結串列      顧名思義,首尾相連的連結串列即是迴圈連結串列。可以是單鏈表,也可以是雙鏈表。     迴圈連結串列是另一種形式的連結串列,它提供了更為靈活的遍歷連結串列元素的能力。迴圈連結串列可以是單向的或雙向的,但區分一個連結串列是

python 實現單向迴圈連結串列

單向迴圈連結串列 特點: 若連結串列為空,則頭結點的next結點還是指向其本身,即head.next=head; 尾節點的next指標指向head結點,即頭尾相連; 判斷是否遍歷了完,直接判斷next==head即可; 由單鏈表變化的迴圈也成為單向迴圈連結串列

C語言資料結構----迴圈連結串列

主要講解釋迴圈連結串列的一些定義和具體的操作。 一、基本定義: 1.單鏈表的侷限:不可以迴圈。2.迴圈連結串列的定義:將單鏈表中最後一個元素的next指向第一個元素。3.迴圈連結串列擁有單鏈表的所有操作。4.迴圈連結串列的插入和單鏈表插入的差別:單鏈表的插入是 n

linux 下c語言建立單向動態連結串列的理解

#include <stdio.h> #include <malloc.h>              //分配記憶體要加上這個庫函式 struct weapon {   int price;   int atk;   struct weapon* next; };  //建立一個武器

華為面試題——約瑟夫問題的C++簡單實現迴圈連結串列

/*     author:jiangxin     Blog:http://blog.csdn.net/jiangxinnju     Function:method of Josephus question */ #include <iostream> us

約瑟夫環(使用C語言單向迴圈連結串列來解決)

題目描述 編號為1,2,…,n的n個人按順時針方向圍坐在一張圓桌周圍,每人持有一個密碼(正整數)。一 開始任選一個正整數m作為報數上限值,從第一個人開始按順時針方向自1開始報數,報到m時停止報數,報m的那 個人出列,將他的密碼作為新的m值,從他順時針方向的下一個人開始重新從1報數,

C語言版)連結串列(四)——實現雙向迴圈連結串列建立、插入、刪除、釋放記憶體等簡單操作

雙向迴圈連結串列是基於雙向連結串列的基礎上實現的,和雙向連結串列的操作差不多,唯一的區別就是它是個迴圈的連結串列,通過每個節點的兩個指標把它們扣在一起組成一個環狀。所以呢,每個節點都有前驅節點和後繼節點(包括頭節點和尾節點)這是和雙向連結串列不同的地方。我們看下雙向迴圈連結

資料結構(三)——單向迴圈連結串列的java實現

單向迴圈連結串列結構就是連結串列的最後一個指標不再是null,而是指向整個連結串列的第一個結點,使連結串列形成一個環。 上程式碼 package likend; /** * Created by yxf on 2018/3/27. * 單向迴圈連結串列 */ publ

資料結構學習筆記——C++實現雙向迴圈連結串列模板類(超詳解)

定義了兩個標頭檔案分別放置結點類模板(Node.h)和雙鏈表模板(DoubleLinkList.h), 然後在原始檔的main函式中測試。 Node.h #pragma once # include <iostream> template <class

利用單向迴圈連結串列結構實現如下記憶體頁置換策略CLOCK Algorithm

利用單向迴圈連結串列結構實現如下記憶體頁置換策略CLOCK Algorithm: 假設緩衝池有6個緩衝頁,以單向迴圈連結串列結構組織,結構如下圖所示。緩衝池初始狀態:所有緩衝頁可用,指標P指向下一個即將被分配的緩衝頁。緩衝池包含的緩衝頁數作為程式執行引數設定,該引數的有效設

C++版)連結串列(二)——實現單項迴圈連結串列建立、插入、刪除等操作

        連結串列(二)單向迴圈連結串列的實現,下面實現程式碼: #include <iostream> #include <stdlib.h> using namespace std; //結點類 class Node { public:

Java 單向連結串列單向迴圈連結串列的程式碼實現

這個連結串列,以前上學的時候,學c語言,還是資料結構的時候,學過。也許也實現過吧。下面我就簡單記錄下這個連結串列的實現。 單向連結串列跟單向迴圈連結串列的差別就是:單向連結串列是有結束位的,指向null的時候,就到結尾了,但是單向迴圈連結串列,他就是一個圈,要是不設定指定位

約瑟夫環 單向迴圈連結串列實現

約瑟夫環 已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。 ///迴圈連結串列實現 #include<bits/stdc++.h>