線性表-單循環(huán)鏈表(含頭指針和尾指針)

image.png

CircleList.h:

#ifndef CIRCLELIST_H_INCLUDED
#define CIRCLELIST_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <malloc.h>
#include <assert.h>

typedef int ElemType ;//數(shù)據(jù)類型
typedef struct Node{
    ElemType data;//數(shù)據(jù)域
    struct Node *next;//下一節(jié)點(diǎn)
}Node,*PNode;
typedef struct CircleList{
    PNode head;
    PNode tail;
    int size;
}CircleList;

void Init_List(CircleList *pList);             //初始化單鏈表
void Show_List(CircleList *pList);         //顯示鏈表內(nèi)容
PNode Buy_Node(ElemType e); //創(chuàng)建一個(gè)新節(jié)點(diǎn)
void Push_Front(CircleList *pList,ElemType e);//頭插法
void Push_Back(CircleList *pList,ElemType e); //尾插法
ElemType Pop_Front(CircleList *pList);            //頭刪法
ElemType Pop_Back(CircleList *pList);             //尾刪法
Node* Find_Val(CircleList *pList,ElemType e,int* index);     //查找函數(shù)滤蝠,找到返回指向該元素的指針
bool Modify_Val(CircleList *pList,ElemType oldVal,ElemType newVal);    //修改某一元素的值
void Delete_Val(CircleList *pList,ElemType e);//按值刪除
void Clear_List(CircleList *pList);                //清空鏈表
void Destroy_List(CircleList *pList);              //銷毀鏈表
int  Length_List(CircleList *pList);               //求鏈表長度
bool IsEmpty_List(CircleList *pList);               //判斷鏈表是否為空
PNode Prio_List(CircleList *pList,ElemType e);      //求某個(gè)值的前驅(qū)
PNode Next_List(CircleList *pList,ElemType e);      //求某個(gè)值的后繼

#endif // CIRCLELIST_H_INCLUDED

CircleList.c:

#include "CircleList.h"


//初始化單鏈表
void Init_List(CircleList *pList){

    PNode p = (PNode)malloc(sizeof(Node)); //初始化一個(gè)結(jié)點(diǎn)
    assert(pList->head != NULL);
    //初始化head和tail指針,使其都指向頭節(jié)點(diǎn)
    pList->tail = pList->head = p;
    pList->head->next=pList->head;
    pList->tail->next=pList->head;
    pList->size=0;
}
 //顯示鏈表內(nèi)容
void Show_List(CircleList *pList){
    if(pList->size<1){
        printf("[]\n");
        return ;
    }
     PNode p = pList->head->next;//第一個(gè)節(jié)點(diǎn)
     bool flag=false;
     printf("[");
     while(p!=pList->head){
        if(flag){
            printf(",");
        }
        flag=true;
        printf("%d",p->data);
        p=p->next;
     }
     printf("]\n");
}
//創(chuàng)建一個(gè)新節(jié)點(diǎn)
PNode Buy_Node(ElemType e){
    PNode p = (PNode)malloc(sizeof(Node)); //初始化一個(gè)結(jié)點(diǎn)
    assert(p != NULL);//斷言,表達(dá)式為真,接著往下執(zhí)行
    p->next=NULL;
    p->data=e;//填充數(shù)據(jù)域
    return p;

}
//頭插法
void Push_Front(CircleList *pList,ElemType e){
    PNode nexNode=Buy_Node(e);//獲取一個(gè)節(jié)點(diǎn)
    nexNode->next=pList->head->next;
    pList->head->next=nexNode;
    //如果是第一次頭插,需改變尾指針和尾節(jié)點(diǎn)的next指向,之后都不改變
    if(pList->size==0){
        pList->tail=nexNode;
    }
    pList->size++;//有效個(gè)數(shù)加1
}
//尾插法
void Push_Back(CircleList *pList,ElemType e){
    PNode nexNode=Buy_Node(e);//獲取一個(gè)節(jié)點(diǎn)
    nexNode->next=pList->tail->next;//單循環(huán)鏈表,新節(jié)點(diǎn)的next指向頭結(jié)點(diǎn)
    pList->tail->next=nexNode; //tail指向最后一個(gè)節(jié)點(diǎn),把新建立的節(jié)點(diǎn)鏈接到鏈表的最后
    pList->tail=nexNode;//改變尾指針的指向
    pList->size++;//有效個(gè)數(shù)加1
    return true;
}
//頭刪法
ElemType Pop_Front(CircleList *pList){

    if(0==pList->size)return 0;
    PNode first=pList->head->next;
    ElemType val=first->data;
     //只有一個(gè)節(jié)點(diǎn)摊腋,若刪去,需改變尾指針
    if(1==pList->size) {
        pList->tail=pList->head;
    }
    pList->head->next=first->next;
    free(first);
    printf("--頭節(jié)點(diǎn)已刪除\n");
    pList->size--;

    return val;
}
//尾刪法
ElemType Pop_Back(CircleList *pList){
    if(0==pList->size)return 0;
    PNode last=pList->tail;
//    PNode p = pList->head->next;
//    while(p->next!=last){////找到倒數(shù)第二個(gè)節(jié)點(diǎn)
//        p=p->next;
//    }
    PNode p = pList->head;
    while(pList->head != p->next->next)      //找到倒數(shù)第二個(gè)節(jié)點(diǎn)
    {
        p = p->next;
    }
    p->next=last->next;
    pList->tail=p;
    ElemType val=last->data;
    free(last);
    printf("--尾節(jié)點(diǎn)已刪除\n");
    pList->size--;
    return val;
}
//查找函數(shù)嘁傀,找到返回指向該元素的指針 即要查找元素的前面一個(gè)的地址 以及下標(biāo)
Node* Find_Val(CircleList *pList,ElemType e,int *index){
    if(0==pList->size){
         printf("--鏈表為空兴蒸!\n");
        return NULL;
    }
    PNode p=pList->head;//第一個(gè)節(jié)點(diǎn)
    int j=0;
    PNode pre;
    bool flag=true;
    while(p->next!=pList->head && flag){//尋找指向這個(gè)元素的指針
        pre=p;
        p=p->next;
        j++;
        if(p->data == e){
            flag=false;
        }
    }

    if(pList->head == pre->next||flag){          //如果p指向最后一個(gè)元素,說明沒有找到
        printf("--沒找到细办!\n");
        if(index){
            *index=-1;
        }
        return NULL;
    }
    if(index){
        *index=j;
    }
    return pre;
}
//修改某一元素的值
bool Modify_Val(CircleList *pList,ElemType oldVal,ElemType newVal){
     PNode p = Find_Val(pList,oldVal,NULL);
     if(!p){
        return false;
     }
     p->next->data=newVal;
     return true;
}
//按值刪除
void Delete_Val(CircleList *pList,ElemType e){
    if(0==pList->size){
         printf("--鏈表為空橙凳!\n");
        return ;
    }
    //尋找到前一個(gè)元素
    PNode pre = Find_Val(pList,e,NULL);
    PNode temp = NULL;//要?jiǎng)h除的節(jié)點(diǎn)
    if(pre){
        temp=pre->next;
        if(temp == pList->tail)        //若刪除最后一個(gè)節(jié)點(diǎn),需改變尾指針
        pList->tail = pre;
        pre->next=temp->next;
        free(temp);
        printf("元素%d已刪除!\n",e);
    }

}
//清空鏈表
void Clear_List(CircleList *pList){
    PNode p=pList->head->next;//p指向第一個(gè)節(jié)點(diǎn)
    PNode temp;
    while(p!=pList->head){
        temp=p->next;
        free(p);//將節(jié)點(diǎn)依次釋放
        p=temp;
    }
    //尾指針以及頭指針都指向頭結(jié)點(diǎn)
    pList->tail = pList->head;
    pList->tail->next= pList->head;
    pList->head->next = pList->head;
    pList->size = 0;
    printf("--鏈表已被清空笑撞!\n");
}
//銷毀鏈表
void Destroy_List(CircleList *pList){
    Clear_List(pList);
    free(pList->head);//頭結(jié)點(diǎn)釋放
    pList->head = NULL;
    pList->tail = NULL;
    printf("--鏈表已被摧毀痕惋!\n");
}
//求鏈表長度
int  Length_List(CircleList *pList){
    if(!pList->head){
         printf("--鏈表未初始化!\n");
        return 0;
    }
    int length=0;
    PNode p=pList->head->next;
    while(p!=pList->head){
        p=p->next;
        length++;
    }
    return length;
}
//判斷鏈表是否為空
bool IsEmpty_List(CircleList *pList){
//    if(pList->size==0){
//        return true;
//    }
      if(pList->head==pList->head->next){
        printf("鏈表為空\n");
        return true;
      }
      return false;

}

//求某個(gè)值的前驅(qū)
PNode Prio_List(CircleList *pList,ElemType e){
    PNode pre = Find_Val(pList,e,NULL);
    if(NULL != pre){
        if(pre == pList->head ) {//首元素?zé)o前驅(qū)
            printf("首元素?zé)o前驅(qū)\n");
            return NULL;
        }
        return pre;
    }
    return NULL;
}
//求某個(gè)值的后繼
PNode Next_List(CircleList *pList,ElemType e){
    PNode pre = Find_Val(pList,e,NULL);
    if(NULL != pre){
        if(pre->next == pList->tail ) {//尾元素?zé)o后繼
            printf("尾元素?zé)o后繼\n");
            return NULL;
        }
        return pre->next->next;
    }
    return NULL;
}

測試:

#include "CircleList.h"
void menu()           //提供選項(xiàng)的菜單函數(shù)
{
    printf("***************************************************************\n");
    printf("* [0] 退出系統(tǒng)    [1] 展示鏈表   [2] 頭插數(shù)據(jù)    [3] 尾插數(shù)據(jù) *\n");
    printf("* [4] 頭刪數(shù)據(jù)    [5] 尾刪數(shù)據(jù)   [6] 查找元素    [7] 修改元素*\n");
    printf("* [8] 按值刪除    [9] 鏈表長度   [10]判斷空鏈表  [11]獲取前驅(qū)  *\n");
    printf("* [12]獲取后繼    [13]獲取前驅(qū)   [14] 銷毀鏈表       *\n");
    printf("***************************************************************\n");
}
int main()
{
    CircleList pList;
    Init_List(&pList);
    ElemType val= 0;
    bool flag=true;
    PNode p = NULL;
    int chose;
    int pos ;
     int index=0;
    while(flag){
         menu();
         printf("輸入序號(hào)選擇您的操作:\n");
         scanf("%d",&chose);
         switch(chose){
            case 0:
                flag=false;
                exit(0);
                break;
            case 1:
                Show_List(&pList);
                break;
            case 2:
                printf("輸入要頭插的數(shù)據(jù)[-1結(jié)束]:\n");
                while(scanf("%d",&val),val!=-1){
                    Push_Front(&pList,val);
                }
                break;
            case 3:
                printf("輸入要尾插的數(shù)據(jù)[-1結(jié)束]:\n");
                while(scanf("%d",&val),val!=-1){
                    Push_Back(&pList,val);
                }
                break;
            case 4:
                Pop_Front(&pList);
                break;
            case 5:
                Pop_Back(&pList);
                break;
            case 6:

                printf("輸入要查找的數(shù)據(jù):\n");
                scanf("%d",&val);
                p = Find_Val(&pList,val,&index);
                if(p){
                    printf("查找的元素為%d,下標(biāo)為:%d",p->next->data,index);
                }
                break;
            case 7:
               printf("輸入要修改的數(shù)和修改后的數(shù)\n");
                scanf("%d %d",&val,&pos);
                Modify_Val(&pList,val,pos);
                break;
            case 8:
                printf("輸入要?jiǎng)h除的數(shù)\n");
                scanf("%d",&val);
                Delete_Val(&pList,val);
                break;
            case 9:
                printf("鏈表的長度為:%d\n",Length_List(&pList));
                break;
            case 10:
                if(!IsEmpty_List(&pList)){
                    printf("鏈表不為空\n");
                }
                break;
            case 11:
                printf("輸入想要找哪個(gè)一數(shù)的前驅(qū):\n");
                scanf("%d",&val);
                p=Prio_List(&pList,val);
                if(p){
                    printf("%d 的前驅(qū)是:%d\n",val,p->data);
                }
                break;
            case 12:
                printf("輸入想要找哪個(gè)一數(shù)的后繼:\n");
                scanf("%d",&val);
                p=Next_List(&pList,val);
                if(p){
                    printf("%d 的前驅(qū)是:%d\n",val,p->data);
                }
                break;
            case 13:
                Clear_List(&pList);
                break;
            case 14:
                Destroy_List(&pList);
                break;
            default:
                printf("重新輸入\n");
            break;
         }
    }
    return 0;
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末娃殖,一起剝皮案震驚了整個(gè)濱河市值戳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炉爆,老刑警劉巖堕虹,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異芬首,居然都是意外死亡赴捞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門郁稍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赦政,“玉大人,你說我怎么就攤上這事耀怜』肿牛” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵财破,是天一觀的道長掰派。 經(jīng)常有香客問我,道長左痢,這世上最難降的妖魔是什么靡羡? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任系洛,我火速辦了婚禮,結(jié)果婚禮上略步,老公的妹妹穿的比我還像新娘描扯。我一直安慰自己,他們只是感情好趟薄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布荆烈。 她就那樣靜靜地躺著,像睡著了一般竟趾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宫峦,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天岔帽,我揣著相機(jī)與錄音,去河邊找鬼导绷。 笑死犀勒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的妥曲。 我是一名探鬼主播贾费,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼檐盟!你這毒婦竟也來了褂萧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤葵萎,失蹤者是張志新(化名)和其女友劉穎导犹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體羡忘,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谎痢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卷雕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片节猿。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖漫雕,靈堂內(nèi)的尸體忽然破棺而出滨嘱,到底是詐尸還是另有隱情,我是刑警寧澤浸间,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布九孩,位于F島的核電站,受9級(jí)特大地震影響发框,放射性物質(zhì)發(fā)生泄漏躺彬。R本人自食惡果不足惜煤墙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宪拥。 院中可真熱鬧仿野,春花似錦、人聲如沸她君。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缔刹。三九已至球涛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間校镐,已是汗流浹背亿扁。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鸟廓,地道東北人从祝。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像引谜,于是被迫代替她去往敵國和親牍陌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 專業(yè)考題類型管理運(yùn)行工作負(fù)責(zé)人一般作業(yè)考題內(nèi)容選項(xiàng)A選項(xiàng)B選項(xiàng)C選項(xiàng)D選項(xiàng)E選項(xiàng)F正確答案 變電單選GYSZ本規(guī)程...
    小白兔去釣魚閱讀 8,981評(píng)論 0 13
  • /*單鏈表的頭插法和尾插法c語言實(shí)現(xiàn)*/ #include #include #include #define S...
    WB莫遙燚閱讀 2,596評(píng)論 0 0
  • 選擇題部分 1.(),只有在發(fā)生短路事故時(shí)或者在負(fù)荷電流較大時(shí),變流器中才會(huì)有足夠的二次電流作為繼電保護(hù)跳閘之用毒涧。...
    skystarwuwei閱讀 12,837評(píng)論 0 7
  • 分類:androidandroid異常框架 ** (432)** (0) 這句子的話意思也很容易理解档玻,“接收者類已...
    魏成閱讀 1,934評(píng)論 0 0
  • 生活是一本書,而你就是它的作者霹琼。 生活中枣申,每次遇到很難解決忠藤,又不得不解決的時(shí)候模孩,拖延并不能不要去做榨咐,反而因?yàn)闀r(shí)間的...
    湘湘5297閱讀 181評(píng)論 0 0