數據結構和算法(二)單向循環鏈表的建立插入刪除實現github
數據結構和算法(五)棧和隊列的操做和實現shell
@TOCswift
回顧一下,前面一篇博客「數據結構和算法(二)單向循環鏈表的建立插入刪除實現」中講解了單向鏈表和單向循環鏈表。 這篇博客主要講解雙向鏈表和雙向循環鏈表的基本操做實現。數據結構
本篇博客的Demo下載:數據結構和算法
單鏈表相對於順序表,確實在某些場景下解決了一些重要的問題,例如在須要插入或者刪除大量元素的時候,它並不須要像順序表同樣移動不少元素,只須要修改指針的指向就能夠了,其時間複雜度爲 O(1) 可是這但是有前提的,那就是這一切都基於肯定節點後,純粹考慮刪除和插入的狀況下,可是若是咱們仍未肯定節點的位置,那麼單鏈表就會出現一些問題了函數
咱們先來對比一下單鏈表和雙鏈表的刪除操做:post
回顧一下前面一篇博客「數據結構和算法(二)單向循環鏈表的建立插入刪除實現」中講解的單向鏈表刪除操做,以下圖咱們要刪除一個結點,假如想要刪除第2個節點 a1 只須要 將首元結點的指針指向到第三個節點的地址去:
可是不管咱們選擇哪種方法,指針的總移動數都會是 2n 次,而雙鏈表卻在這一類型問題上作出了很好的處理。
咱們接下來看一下雙鏈表的刪除結點的過程:
咱們能夠計算一下它們刪除是的操做數量:
雙鏈表雖然解決了單鏈表中的反向查找痛點,可是是以每一個結點增長了一個指針域爲代價的,也就是用空間來換取的。
接下來,咱們來了解一下雙向鏈表的基本操做代碼實現。
//定義結點
typedef struct KNode{
KElementType data; //數據
struct KNode *prior; //前驅指針 struct KNode *next; //後繼指針 }Node; 複製代碼
//5.1 建立雙向連接
KStatus createLinkList(LinkList *L){
//*L 指向頭結點
*L = (LinkList)malloc(sizeof(KNode));
if (*L == NULL) return ERROR;
(*L)->prior = NULL;
(*L)->next = NULL;
(*L)->data = -1;
//新增數據
LinkList p = *L;
for(int i=0; i < 10;i++){
//1.建立1個臨時的結點
LinkList temp = (LinkList)malloc(sizeof(KNode));
temp->prior = NULL;
temp->next = NULL;
temp->data = i;
//2.爲新增的結點創建雙向鏈表關係
//① temp 是p的後繼
p->next = temp;
//② temp 的前驅是p
temp->prior = p;
//③ p 要記錄最後的結點的位置,方便下一次插入
p = p->next;
}
return OK;
}
複製代碼
在第i個位置插入元素,大概步驟以下:
插入結點的實現代碼以下:
//5.3 雙向鏈表插入元素
KStatus ListInsert(LinkList *L, int i, KElementType data){
//1. 插入的位置不合法 爲0或者爲負數
if(i < 1) return ERROR;
//2. 新建結點
LinkList temp = (LinkList)malloc(sizeof(KNode));
temp->data = data;
temp->prior = NULL;
temp->next = NULL;
//3.將p指向頭結點!
LinkList p = *L;
//4. 找到插入位置i直接的結點
for(int j = 1; j < i && p;j++)
p = p->next;
//5. 若是插入的位置超過鏈表自己的長度
if(p == NULL){
return ERROR;
}
//6. 判斷插入位置是否爲鏈表尾部;
if (p->next == NULL) {
p->next = temp;
temp->prior = p;
}else
{
//1️⃣ 將p->next 結點的前驅prior = temp
p->next->prior = temp;
//2️⃣ 將temp->next 指向原來的p->next
temp->next = p->next;
//3️⃣ p->next 更新成新建立的temp
p->next = temp;
//4️⃣ 新建立的temp前驅 = p
temp->prior = p;
}
return OK;
}
複製代碼
刪除第i個位置的元素,大概步驟以下:
刪除結點的代碼實現以下: (1) 刪除雙向鏈表指定位置上的結點
//5.4 刪除雙向鏈表指定位置上的結點
KStatus ListDelete(LinkList *L, int i, KElementType *e){
int k = 1;
LinkList p = (*L);
//1.判斷雙向鏈表是否爲空,若是爲空則返回ERROR;
if (*L == NULL) {
return ERROR;
}
//2. 將指針p移動到刪除元素位置前一個
while (k < i && p != NULL) {
p = p->next;
k++;
}
//3.若是k>i 或者 p == NULL 則返回ERROR
if (k>i || p == NULL) {
return ERROR;
}
//4.建立臨時指針delTemp 指向要刪除的結點,並將要刪除的結點的data 賦值給*e,帶回到main函數
LinkList delTemp = p->next;
*e = delTemp->data;
//5. p->next 等於要刪除的結點的下一個結點
p->next = delTemp->next;
//6. 若是刪除結點的下一個結點不爲空,則將將要刪除的下一個結點的前驅指針賦值p;
if (delTemp->next != NULL) {
delTemp->next->prior = p;
}
//7.刪除delTemp結點
free(delTemp);
return OK;
}
複製代碼
(2) 刪除雙向鏈表指定的元素
//5.5 刪除雙向鏈表指定的元素
KStatus LinkListDeletVAL(LinkList *L, int data){
LinkList p = *L;
//1.遍歷雙向循環鏈表
while (p) {
//2.判斷當前結點的數據域和data是否相等,若相等則刪除該結點
if (p->data == data) {
//修改被刪除結點的前驅結點的後繼指針,參考圖上步驟1️⃣
p->prior->next = p->next;
//修改被刪除結點的後繼結點的前驅指針,參考圖上步驟2️⃣
if(p->next != NULL){
p->next->prior = p->prior;
}
//釋放被刪除結點p
free(p);
//退出循環
break;
}
//沒有找到該結點,則繼續移動指針p
p = p->next;
}
return OK;
}
複製代碼
//5.2 打印循環鏈表的元素
void display(LinkList L){
LinkList temp = L->next;
if(temp == NULL){
printf("打印的雙向鏈表爲空!\n");
return;
}
while (temp) {
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
複製代碼
//5.6.1 在雙向鏈表中查找元素
int selectElem(LinkList L,KElementType elem){
LinkList p = L->next;
int i = 1;
while (p) {
if (p->data == elem) {
return i;
}
i++;
p = p->next;
}
return -1;
}
複製代碼
//5.6.2 在雙向鏈表中更新結點
KStatus replaceLinkList(LinkList *L,int index,KElementType newElem){
LinkList p = (*L)->next;
for (int i = 1; i < index; i++) {
p = p->next;
}
p->data = newElem;
return OK;
}
複製代碼
void test () {
KStatus iStatus = 0;
LinkList L;
int temp,item,e;
iStatus = createLinkList(&L);
printf("iStatus = %d\n",iStatus);
printf("鏈表建立成功,打印鏈表:\n");
display(L);
printf("請輸入插入的位置\n");
scanf("%d %d",&temp,&item);
iStatus = ListInsert(&L, temp, item);
printf("插入數據,打印鏈表:\n");
display(L);
printf("請輸入插入的位置\n");
scanf("%d %d",&temp,&item);
iStatus = ListInsert(&L, temp, item);
printf("插入數據,打印鏈表:\n");
display(L);
printf("請輸入插入的位置\n");
scanf("%d %d",&temp,&item);
iStatus = ListInsert(&L, temp, item);
printf("插入數據,打印鏈表:\n");
display(L);
printf("請輸入刪除的位置\n");
scanf("%d",&temp);
iStatus = ListDelete(&L, temp, &e);
printf("刪除元素: 刪除位置爲%d,data = %d\n",temp,e);
printf("刪除操做以後的,雙向鏈表:\n");
display(L);
printf("請輸入你要刪除的內容\n");
scanf("%d",&temp);
iStatus = LinkListDeletVAL(&L, temp);
printf("刪除指定data域等於%d的結點,雙向鏈表:\n",temp);
display(L);
printf("請輸入你要查找的內容\n");
scanf("%d",&temp);
KElementType index = selectElem(L, temp);
printf("在雙向鏈表中查找到數據域爲%d的結點,位置是:%d\n",temp,index);
printf("請輸入你要更新的結點以及內容\n");
scanf("%d %d",&temp,&item);
iStatus = replaceLinkList(&L, temp, item);
printf("更新結點數據後的雙向鏈表:\n");
display(L);
}
複製代碼
輸出結果:
Hello, World!
iStatus = 1
鏈表建立成功,打印鏈表:
0 1 2 3 4 5 6 7 8 9
請輸入插入的位置
1 66
插入數據,打印鏈表:
66 0 1 2 3 4 5 6 7 8 9
請輸入插入的位置
10 66
插入數據,打印鏈表:
66 0 1 2 3 4 5 6 7 66 8 9
請輸入插入的位置
12 77
插入數據,打印鏈表:
66 0 1 2 3 4 5 6 7 66 8 77 9
請輸入刪除的位置
1 66
刪除元素: 刪除位置爲1,data = 66
刪除操做以後的,雙向鏈表:
0 1 2 3 4 5 6 7 66 8 77 9
請輸入你要刪除的內容
刪除指定data域等於66的結點,雙向鏈表:
0 1 2 3 4 5 6 7 8 77 9
請輸入你要查找的內容
77
在雙向鏈表中查找到數據域爲77的結點,位置是:10
請輸入你要更新的結點以及內容
複製代碼
//
// main.c
// 005_DoubleLinkedList
//
// Created by 孔雨露 on 2020/4/5.
// Copyright © 2020 Apple. All rights reserved.
//
#include <stdio.h>
#include "string.h"
#include "ctype.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OK 1
#define MAXSIZE 20 /* 存儲空間初始分配量 */
typedef int KStatus;/* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */
typedef int KElementType;/* KElementType類型根據實際狀況而定,這裏假設爲int */
//定義結點
typedef struct KNode{
KElementType data;
struct KNode *prior; struct KNode *next; }KNode; typedef struct KNode * LinkList; //5.1 建立雙向連接 KStatus createLinkList(LinkList *L){
//*L 指向頭結點
*L = (LinkList)malloc(sizeof(KNode));
if (*L == NULL) return ERROR;
(*L)->prior = NULL;
(*L)->next = NULL;
(*L)->data = -1;
//新增數據
LinkList p = *L;
for(int i=0; i < 10;i++){
//1.建立1個臨時的結點
LinkList temp = (LinkList)malloc(sizeof(KNode));
temp->prior = NULL;
temp->next = NULL;
temp->data = i;
//2.爲新增的結點創建雙向鏈表關係
//① temp 是p的後繼
p->next = temp;
//② temp 的前驅是p
temp->prior = p;
//③ p 要記錄最後的結點的位置,方便下一次插入
p = p->next;
}
return OK;
}
//5.2 打印循環鏈表的元素
void display(LinkList L){
LinkList temp = L->next;
if(temp == NULL){
printf("打印的雙向鏈表爲空!\n");
return;
}
while (temp) {
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
//5.3 雙向鏈表插入元素
KStatus ListInsert(LinkList *L, int i, KElementType data){
//1. 插入的位置不合法 爲0或者爲負數
if(i < 1) return ERROR;
//2. 新建結點
LinkList temp = (LinkList)malloc(sizeof(KNode));
temp->data = data;
temp->prior = NULL;
temp->next = NULL;
//3.將p指向頭結點!
LinkList p = *L;
//4. 找到插入位置i直接的結點
for(int j = 1; j < i && p;j++)
p = p->next;
//5. 若是插入的位置超過鏈表自己的長度
if(p == NULL){
return ERROR;
}
//6. 判斷插入位置是否爲鏈表尾部;
if (p->next == NULL) {
p->next = temp;
temp->prior = p;
}else
{
//1️⃣ 將p->next 結點的前驅prior = temp
p->next->prior = temp;
//2️⃣ 將temp->next 指向原來的p->next
temp->next = p->next;
//3️⃣ p->next 更新成新建立的temp
p->next = temp;
//4️⃣ 新建立的temp前驅 = p
temp->prior = p;
}
return OK;
}
//5.4 刪除雙向鏈表指定位置上的結點
KStatus ListDelete(LinkList *L, int i, KElementType *e){
int k = 1;
LinkList p = (*L);
//1.判斷雙向鏈表是否爲空,若是爲空則返回ERROR;
if (*L == NULL) {
return ERROR;
}
//2. 將指針p移動到刪除元素位置前一個
while (k < i && p != NULL) {
p = p->next;
k++;
}
//3.若是k>i 或者 p == NULL 則返回ERROR
if (k>i || p == NULL) {
return ERROR;
}
//4.建立臨時指針delTemp 指向要刪除的結點,並將要刪除的結點的data 賦值給*e,帶回到main函數
LinkList delTemp = p->next;
*e = delTemp->data;
//5. p->next 等於要刪除的結點的下一個結點
p->next = delTemp->next;
//6. 若是刪除結點的下一個結點不爲空,則將將要刪除的下一個結點的前驅指針賦值p;
if (delTemp->next != NULL) {
delTemp->next->prior = p;
}
//7.刪除delTemp結點
free(delTemp);
return OK;
}
//5.5 刪除雙向鏈表指定的元素
KStatus LinkListDeletVAL(LinkList *L, int data){
LinkList p = *L;
//1.遍歷雙向循環鏈表
while (p) {
//2.判斷當前結點的數據域和data是否相等,若相等則刪除該結點
if (p->data == data) {
//修改被刪除結點的前驅結點的後繼指針,參考圖上步驟1️⃣
p->prior->next = p->next;
//修改被刪除結點的後繼結點的前驅指針,參考圖上步驟2️⃣
if(p->next != NULL){
p->next->prior = p->prior;
}
//釋放被刪除結點p
free(p);
//退出循環
break;
}
//沒有找到該結點,則繼續移動指針p
p = p->next;
}
return OK;
}
//5.6.1 在雙向鏈表中查找元素
int selectElem(LinkList L,KElementType elem){
LinkList p = L->next;
int i = 1;
while (p) {
if (p->data == elem) {
return i;
}
i++;
p = p->next;
}
return -1;
}
//5.6.2 在雙向鏈表中更新結點
KStatus replaceLinkList(LinkList *L,int index,KElementType newElem){
LinkList p = (*L)->next;
for (int i = 1; i < index; i++) {
p = p->next;
}
p->data = newElem;
return OK;
}
void test () {
KStatus iStatus = 0;
LinkList L;
int temp,item,e;
iStatus = createLinkList(&L);
printf("iStatus = %d\n",iStatus);
printf("鏈表建立成功,打印鏈表:\n");
display(L);
printf("請輸入插入的位置\n");
scanf("%d %d",&temp,&item);
iStatus = ListInsert(&L, temp, item);
printf("插入數據,打印鏈表:\n");
display(L);
printf("請輸入插入的位置\n");
scanf("%d %d",&temp,&item);
iStatus = ListInsert(&L, temp, item);
printf("插入數據,打印鏈表:\n");
display(L);
printf("請輸入插入的位置\n");
scanf("%d %d",&temp,&item);
iStatus = ListInsert(&L, temp, item);
printf("插入數據,打印鏈表:\n");
display(L);
printf("請輸入刪除的位置\n");
scanf("%d",&temp);
iStatus = ListDelete(&L, temp, &e);
printf("刪除元素: 刪除位置爲%d,data = %d\n",temp,e);
printf("刪除操做以後的,雙向鏈表:\n");
display(L);
printf("請輸入你要刪除的內容\n");
scanf("%d",&temp);
iStatus = LinkListDeletVAL(&L, temp);
printf("刪除指定data域等於%d的結點,雙向鏈表:\n",temp);
display(L);
printf("請輸入你要查找的內容\n");
scanf("%d",&temp);
KElementType index = selectElem(L, temp);
printf("在雙向鏈表中查找到數據域爲%d的結點,位置是:%d\n",temp,index);
printf("請輸入你要更新的結點以及內容\n");
scanf("%d %d",&temp,&item);
iStatus = replaceLinkList(&L, temp, item);
printf("更新結點數據後的雙向鏈表:\n");
display(L);
}
int main(int argc, const char * argv[]) {
// insert code here...
printf("Hello, World!\n");
test();
return 0;
}
複製代碼
雙向循環鏈表的結點定義和雙向鏈表是同樣的
//定義結點
typedef struct KNode{
KElementType data;
struct KNode *prior; struct KNode *next; }KNode; 複製代碼
建表過程,實際上就是從一個空表,按照咱們給到的數據建立一個非空鏈表的過程。
以下圖定義的是一個空的雙向循環鏈表,帶頭結點的,頭結點的前驅指針prior和後繼指針next都指向它本身:
以下圖:是上面空鏈表一次從尾部插入A,B元素後獲得的鏈表,另外咱們還能夠從首部插入B,A 元素,也能夠獲得下面的表:
下面的代碼是循環鏈表建立過程,代碼中咱們經過尾部插入法,插入0,1,2,3,4,5,6,7,8,9 總共10個元素。
//6.1 雙向循環鏈表初始化
KStatus creatLinkList(LinkList *L){
*L = (LinkList)malloc(sizeof(KNode));
if (*L == NULL) {
return ERROR;
}
(*L)->next = (*L);
(*L)->prior = (*L);
//新增數據
LinkList p = *L;
for(int i=0; i < 10;i++){
//1.建立1個臨時的結點
LinkList temp = (LinkList)malloc(sizeof(KNode));
temp->data = i;
//2.爲新增的結點創建雙向鏈表關係
//① temp 是p的後繼
p->next = temp;
//② temp 的前驅是p
temp->prior = p;
//③ temp的後繼是*L
temp->next = (*L);
//④ p 的前驅是新建的temp
p->prior = temp;
//⑤ p 要記錄最後的結點的位置,方便下一次插入
p = p->next;
}
return OK;
}
複製代碼
雙向循環鏈表的插入過程以下:
temp->data = e;
temp->prior = p;
temp->next = p->next;
p->next = temp;
(*L)->prior = temp;
;若是不是是則將temp節點的下一個結點的前驅爲temp 結點:temp->next->prior = temp;
插入結點的代碼實現以下:
//6.2 雙向循環鏈表插入元素
/*當插入位置超過鏈表長度則插入到鏈表末尾*/
KStatus LinkListInsert(LinkList *L, int index, KElementType e){
//1. 建立指針p,指向雙向鏈表頭
LinkList p = (*L);
int i = 1;
//2.雙向循環鏈表爲空,則返回error
if(*L == NULL) return ERROR;
//3.找到插入前一個位置上的結點p
while (i < index && p->next != *L) {
p = p->next;
i++;
}
//4.若是i>index 則返回error
if (i > index) return ERROR;
//5.建立新結點temp
LinkList temp = (LinkList)malloc(sizeof(KNode));
//6.temp 結點爲空,則返回error
if (temp == NULL) return ERROR;
//7.將生成的新結點temp數據域賦值e.
temp->data = e;
//8.將結點temp 的前驅結點爲p;
temp->prior = p;
//9.temp的後繼結點指向p->next;
temp->next = p->next;
//10.p的後繼結點爲新結點temp;
p->next = temp;
//若是temp 結點不是最後一個結點
if (*L != temp->next) {
//11.temp節點的下一個結點的前驅爲temp 結點
temp->next->prior = temp;
}else{
(*L)->prior = temp;
}
return OK;
}
複製代碼
循環雙鏈表刪除結點的過程以下:
*e = temp->data;
temp->prior->next = temp->next;
(也就B結點的前驅結點A的next指向B結點的後繼C)temp->next->prior = temp->prior;
(讓B結點的後繼結點C的前驅指針指向B結點的前驅A)free(temp);
循環雙鏈表刪除結點的實現代碼以下:
//6.4 雙向循環鏈表刪除結點
KStatus LinkListDelete(LinkList *L,int index,KElementType *e){
int i = 1;
LinkList temp = (*L)->next;
if (*L == NULL) {
return ERROR;
}
//①.若是刪除到只剩下首元結點了,則直接將*L置空;
if(temp->next == *L){
free(*L);
(*L) = NULL;
return OK;
}
//1.找到要刪除的結點
while (i < index) {
temp = temp->next;
i++;
}
//2.給e賦值要刪除結點的數據域
*e = temp->data;
//3.修改被刪除結點的前驅結點的後繼指針 圖1️⃣
temp->prior->next = temp->next;
//4.修改被刪除結點的後繼結點的前驅指針 圖2️⃣
temp->next->prior = temp->prior;
//5. 刪除結點temp
free(temp);
return OK;
}
複製代碼
//6.3 遍歷雙向循環鏈表
KStatus Display(LinkList L){
if (L == NULL) {
printf("打印的雙向循環鏈表爲空!\n\n");
return ERROR;
}
printf("雙向循環鏈表內容: ");
LinkList p = L->next;
while (p != L) {
printf("%d ",p->data);
p = p->next;
}
printf("\n\n");
return OK;
}
複製代碼
void test() {
LinkList L;
KStatus iStatus;
KElementType temp,item;
iStatus = creatLinkList(&L);
printf("雙向循環鏈表初始化是否成功(1->YES)/ (0->NO): %d\n\n",iStatus);
Display(L);
printf("輸入要插入的位置和數據用空格隔開:");
scanf("%d %d",&temp,&item);
iStatus = LinkListInsert(&L,temp,item);
Display(L);
printf("輸入要刪除位置:");
scanf("%d",&temp);
iStatus = LinkListDelete(&L, temp, &item);
printf("刪除鏈表位置爲%d,結點數據域爲:%d\n",temp,item);
Display(L);
}
複製代碼
輸出結果:
Hello, World!
雙向循環鏈表初始化是否成功(1->YES)/ (0->NO): 1
雙向循環鏈表內容: 0 1 2 3 4 5 6 7 8 9
輸入要插入的位置和數據用空格隔開:1 88
雙向循環鏈表內容: 88 0 1 2 3 4 5 6 7 8 9
輸入要刪除位置:1 88
刪除鏈表位置爲1,結點數據域爲:88
雙向循環鏈表內容: 0 1 2 3 4 5 6 7 8 9
複製代碼
//
// main.c
// 006_DoubleCircularLinkList
//
// Created by 孔雨露 on 2020/4/5.
// Copyright © 2020 Apple. All rights reserved.
//
#include <stdio.h>
#include "string.h"
#include "ctype.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OK 1
#define MAXSIZE 20 /* 存儲空間初始分配量 */
typedef int KStatus;/* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */
typedef int KElementType;/* KElementType類型根據實際狀況而定,這裏假設爲int */
//定義結點
typedef struct KNode{
KElementType data;
struct KNode *prior; struct KNode *next; }KNode; typedef struct KNode * LinkList; //6.1 雙向循環鏈表初始化 KStatus creatLinkList(LinkList *L){
*L = (LinkList)malloc(sizeof(KNode));
if (*L == NULL) {
return ERROR;
}
(*L)->next = (*L);
(*L)->prior = (*L);
//新增數據
LinkList p = *L;
for(int i=0; i < 10;i++){
//1.建立1個臨時的結點
LinkList temp = (LinkList)malloc(sizeof(KNode));
temp->data = i;
//2.爲新增的結點創建雙向鏈表關係
//① temp 是p的後繼
p->next = temp;
//② temp 的前驅是p
temp->prior = p;
//③ temp的後繼是*L
temp->next = (*L);
//④ p 的前驅是新建的temp
p->prior = temp;
//⑤ p 要記錄最後的結點的位置,方便下一次插入
p = p->next;
}
return OK;
}
//6.2 雙向循環鏈表插入元素
/*當插入位置超過鏈表長度則插入到鏈表末尾*/
KStatus LinkListInsert(LinkList *L, int index, KElementType e){
//1. 建立指針p,指向雙向鏈表頭
LinkList p = (*L);
int i = 1;
//2.雙向循環鏈表爲空,則返回error
if(*L == NULL) return ERROR;
//3.找到插入前一個位置上的結點p
while (i < index && p->next != *L) {
p = p->next;
i++;
}
//4.若是i>index 則返回error
if (i > index) return ERROR;
//5.建立新結點temp
LinkList temp = (LinkList)malloc(sizeof(KNode));
//6.temp 結點爲空,則返回error
if (temp == NULL) return ERROR;
//7.將生成的新結點temp數據域賦值e.
temp->data = e;
//8.將結點temp 的前驅結點爲p;
temp->prior = p;
//9.temp的後繼結點指向p->next;
temp->next = p->next;
//10.p的後繼結點爲新結點temp;
p->next = temp;
//若是temp 結點不是最後一個結點
if (*L != temp->next) {
//11.temp節點的下一個結點的前驅爲temp 結點
temp->next->prior = temp;
}else{
(*L)->prior = temp;
}
return OK;
}
//6.3 遍歷雙向循環鏈表
KStatus Display(LinkList L){
if (L == NULL) {
printf("打印的雙向循環鏈表爲空!\n\n");
return ERROR;
}
printf("雙向循環鏈表內容: ");
LinkList p = L->next;
while (p != L) {
printf("%d ",p->data);
p = p->next;
}
printf("\n\n");
return OK;
}
//6.4 雙向循環鏈表刪除結點
KStatus LinkListDelete(LinkList *L,int index,KElementType *e){
int i = 1;
LinkList temp = (*L)->next;
if (*L == NULL) {
return ERROR;
}
//①.若是刪除到只剩下首元結點了,則直接將*L置空;
if(temp->next == *L){
free(*L);
(*L) = NULL;
return OK;
}
//1.找到要刪除的結點
while (i < index) {
temp = temp->next;
i++;
}
//2.給e賦值要刪除結點的數據域
*e = temp->data;
//3.修改被刪除結點的前驅結點的後繼指針 圖1️⃣
temp->prior->next = temp->next;
//4.修改被刪除結點的後繼結點的前驅指針 圖2️⃣
temp->next->prior = temp->prior;
//5. 刪除結點temp
free(temp);
return OK;
}
void test() {
LinkList L;
KStatus iStatus;
KElementType temp,item;
iStatus = creatLinkList(&L);
printf("雙向循環鏈表初始化是否成功(1->YES)/ (0->NO): %d\n\n",iStatus);
Display(L);
printf("輸入要插入的位置和數據用空格隔開:");
scanf("%d %d",&temp,&item);
iStatus = LinkListInsert(&L,temp,item);
Display(L);
printf("輸入要刪除位置:");
scanf("%d",&temp);
iStatus = LinkListDelete(&L, temp, &item);
printf("刪除鏈表位置爲%d,結點數據域爲:%d\n",temp,item);
Display(L);
}
int main(int argc, const char * argv[]) {
// insert code here...
printf("Hello, World!\n");
test();
return 0;
}
複製代碼