數據結構手把手教學——雙向循環鏈表

一、雙向循環鏈表

雙向循環鏈表

二、用C語言實現雙向循環鏈表

1、構造存儲結構
typedef int datatype;

typedef struct doublelist{
      datatype data;
      struct doublelist *next, *prev;
}double_list, *double_plist;
2、初始化

初始化主要工作:①申請頭結點內存空間;②head->next = head; head->prev = head;

初始化

3、插入結點

(1)、向p指向的結點後面插入new指向的結點
在這裏插入圖片描述

步驟①:new->next = p->next;
步驟②:p->next->prev = new;
步驟③:new->prev =p;
步驟④:p->next = new;

/* 向p指向的結點後面插入new指向的結點 */
void insert_doublelist_behind(double_plist p, double_plist new)
{
      new->next = p->next;
      p->next->prev = new;
      new->prev = p;
      p->next = new;
}

(2)、向p指向的結點前面插入new指向的結點

在這裏插入圖片描述

步驟①:new->prev = p->prev;
步驟②:p->prev->next = new;
步驟③:new->next = p;
步驟④:p->prev = new;

/* 向p指向的結點前面插入new指向的結點 */
void insert_doublelist_tail(double_plist p, double_plist new)
{
      new->prev = p->prev;
      p->prev->next = new;
      new->next = p;
      p->prev = new;
}
4、刪除結點

(1)、刪除p指向的結點後面的結點
在這裏插入圖片描述

t = p->next;
p->next = t->next;
t->next->prev = p;
free(t);

/* 刪除p指向的結點後面的結點 */
void delete_doublelist_post(double_plist p)
{      
      double_plist t = NULL;
      
      t = p->next;
      p->next = t->next;
      t->next->prev = p;
      free(t);
}

(2)、刪除p指向的結點前面的結點
在這裏插入圖片描述

t = p->prev;
p->prev = t->prev;
t->prev->next = p;
free(t);

/* 刪除p指向的結點前面的結點 */
void delete_doublelist_prev(double_plist p)
{
      double_plist t = NULL;

      t = p->prev;
      p->prev = t->prev;
      t->prev->next = p;
      free(t);
}

(3)、刪除p指向的結點
在這裏插入圖片描述

p->prev->next = p->next;
p->next->prev = p->prev;
free(p);

/*  刪除p指向的結點*/
void delete_doublelist(double_plist p)
{
      p->prev->next = p->next;
      p->next->prev = p->prev;
      free(p);
}
5、判斷鏈表是否爲空

判斷head->next == head 是否成立即可。

/* 判斷鏈表是否爲空 */
bool isempty_doublelist(double_plist head)
{
      if (head == head->next)
      {
            return true;
      }
      else
      {
            return false;
      }  
}
6、打印鏈表
void show_doublelist(double_plist head)
{
      double_plist p = NULL;

      for (p = head->next; p != head; p = p->next)
      {
            printf("%d\t", p->data);
      }
      printf("\n");
}

三、練習題

用雙向循環鏈表實順序遞增存儲若干自然數,比如輸入一個整數10,則建立一個雙向循環鏈表,裏面的每個節點分別存放1,2,3,4,5,6,7,8,9,10,然後通過某些操作,將其重新排列成1,3,5,7,9,10,8,6,4,2,即奇數升序偶數降序,並在屏幕上打印出來。

1、創建鏈表
/* 創建鏈表 */
void create_doublelist(double_plist head)
{
      int n = 0;
      int i = 0;
      double_plist new = NULL;

      printf("請輸入要插入的數據個數:");
      scanf("%d", &n);

      for (i=0; i<n; i++)
      {
            new = (double_plist)malloc(sizeof(double_list));
            if (NULL == new)
            {
                  perror("malloc");
                  exit(1);
            }
            printf("輸入要插入的第%d個數據:", i+1);
            scanf("%d", &(new->data));

            /* 使用前插方法 */
            insert_doublelist_tail(head, new);
            show_doublelist(head);
      }
}
2、排序
/* 排序 */
void sort_doublelist(double_plist head)
{
      double_plist p = NULL;
      double_plist t = NULL;

      p = head->prev;   /* p指向最後那個結點,從後往前找 */
      while (p != head)
      {
            if (1 == (p->data % 2))    /* 判斷是否爲奇數 */
            {
                  p = p->prev; /* 如果是奇數,p往前移 */
            }
            else  /* 偶數 */
            {
                  t = p; /* 保存這個結點的數據 */
                  p = p->prev; /* p繼續往前移 */
                  delete_doublelist(t);   /* 刪除這個結點,但不釋放它,還繼續保存數據 */
                  insert_doublelist_tail(head, t); /* 將t結點作爲新結點插入到head結點後面 */
                  show_doublelist(head);
            }
            
      }
}
3、main函數
int main(void)
{
      double_plist head = NULL;

      init_doublelist(&head);
      create_doublelist(head);
      sort_doublelist(head);

      return 0;
}
4、實驗結果

在這裏插入圖片描述

四、完整代碼

https://github.com/sanjaywu/DataStructure

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章