數據結構-單鏈表-結構體定義


單鏈表,用於存儲邏輯關系為 "一對一" 的數據,與順序表不同,鏈表不限制數據的物理存儲狀態,換句話說,使用鏈表存儲的數據元素,其物理存儲位置是隨機的。

結點在存儲器中的位置是任意的,即邏輯上相鄰的數據元素在物理上不一定相鄰。

例如{1,2,3}:

  

線性表的鏈式表示又稱為非順序映像或鏈式映像。

各結點由兩個域組成: 

  數據域:存儲元素數值數據

  指針域:存儲直接后繼結點的存儲位置  

    

頭指針是指向鏈表中第一個結點的指針

首元結點是指鏈表中存儲第一個數據元素a1的結點

頭結點是在鏈表的首元結點之前附設的一個結點;數據域內只放空表標志和表長等信息

如何表示空表?

答:有頭結點時,當頭結點的指針域為空時表示空表

在鏈表中設置頭結點有什么好處?

答:⒈便於首元結點的處理

    首元結點的地址保存在頭結點的指針域中,所以在鏈表的第一個位置上的操作和其它位置一致,無須進行特殊處理;

  ⒉便於空表和非空表的統一處理

    無論鏈表是否為空,頭指針都是指向頭結點的非空指針,因此空表和非空表的處理也就統一了。

頭結點的數據域內裝的是什么?

答:頭結點的數據域可以為空,也可存放線性表長度等附加信息,但此結點不能計入鏈表長度值。

鏈表(鏈式存儲結構)的特點:

1)結點在存儲器中的位置是任意的,即邏輯上相鄰的數據元素在物理上不一定相鄰

2)訪問時只能通過頭指針進入鏈表,並通過每個結點的指針域向后掃描其余結點,所以尋找第一個結點和最后一個結點所花費的時間不等

這種存取元素的方法被稱為順序存取法

鏈表的優缺點:

優點:數據元素的個數可以自由擴充

   插入、刪除等操作不必移動數據,只需修改鏈接指針,修改效率較高鏈表的優缺點

缺點:存儲密度小

   存取效率不高,必須采用順序存取,即存取數據元素時,只能按鏈表的順序進行訪問(順藤摸瓜)

單鏈表是由表頭唯一確定,因此單鏈表可以用頭指針的名字來命名

若頭指針名是L,則把鏈表稱為表L

用c++描述的單鏈表大致可以分兩種,一種用結構體定義,一種用類定義;

鏈表也可以分為頭插法和尾插法

頭插法

生成新結點
將讀入數據存放到新結點的數據域中
將該新結點插入到鏈表的前端

  1 #include<iostream>
  2 using namespace std;
  3 
  4 typedef struct SingLinkList {
  5     int data;                  //數據域
  6     struct SingLinkList *next; //指針域
  7 }SLL,*Slist; //相當於struct SingLinkList,*Slist相當於struct SingLinkList *
  8 
  9 //新建鏈表,確認鏈表的長度
 10 void New_LinkList(Slist L,int n)  //Slist L相當於struct SingLinkList * L
 11 {
 12     int i;
 13     int v;
 14     Slist p;
 15     L->next = NULL;      
 16     
 17     //這是用前插法創建鏈表,此時就不需要使用尾結點了
 18     //所以遍歷的結果是與輸入值的順序是相反的
 19     for (int i = n; i > 0; i--)
 20     {
 21         p = (Slist)malloc(sizeof(SLL));
 22         cin >> v;
 23         p->data = v;
 24         p->next = L->next;  //p的指針域指向L的指針域,即p指向空,
 25         L->next = p;        //但是此時只有p這個結點,還需要頭結點指向p
 26                             //此時頭結點指向p,而p指針域指向最后,
 27                       //可以認為p是尾結點,它的指針域自然要指向空了。
 28          //然后你需要幾個結點就繼續按照原來的一直干下去。記住這是前插法。
 29         //單鏈表的結點不像數組可以通過下標找到,它得從頭開始找。
 30         //每個節點都與上一個結點相連沒有名字是地址傳地址
 31     }
 32 }
 33 
 34 // 獲取鏈表中指定位置的數據元素
 35 int GetElem_LinkList( Slist L, int i, int *e)
 36 {
 37     Slist p;
 38     p = L->next;
 39     int j = 1;
 40 
 41     while (p && j < i)
 42     {
 43         p = p->next;
 44         ++j;
 45     }
 46 
 47     if (!p || j > i)
 48     {
 49         return 0;
 50     }
 51 
 52     *e = p->data;
 53     return 1;
 54 }
 55 
 56 // 在鏈表中指定位置插入數據
 57 int Isert_LinkList(Slist L, int i, int* e)
 58 {
 59     Slist p, s;
 60     p = L;
 61     int j = 0;
 62 
 63     while (p && j < i - 1)
 64     {
 65         p = p->next;
 66         ++j;
 67     }
 68 
 69     if (!p || j > i - 1)
 70     {
 71         return 0;
 72     }
 73 
 74     s = (Slist)malloc(sizeof(SLL));
 75     s->data = *e;
 76     s->next = p->next;
 77     p->next = s;
 78 
 79     return 1;
 80 }
 81 
 82 // 刪除鏈表中指定數據元素
 83 int Delete_LinkList(Slist L, int i, int* e)
 84 {
 85     Slist p, q;
 86     p = L;
 87     int j = 0;
 88 
 89     while (p->next && j < i - 1)
 90     {
 91         p = p->next;
 92         ++j;
 93     }
 94 
 95     if (!(p->next) || j > i - 1)
 96     {
 97         return 0;
 98     }
 99 
100 
101     q = p->next;
102     p->next = q->next;
103     *e = q->data;
104 
105     free(q);
106     return 1;
107 }
108 
109 // 顯示鏈表元素的內容
110 int Print_LinkList(Slist L, char* s)
111 {
112     Slist p;
113     
114     p = L->next;
115     if (p == NULL)
116     {
117         cout << "該鏈表為空!" << endl;
118         return 0;
119     }
120 
121     while (p != NULL)
122     {
123         cout << p->data << " ";
124         p = p->next;
125     }
126     cout << endl;
127     return 1;
128 }
129 
130 int main()
131 {
132     // 創建並初始化鏈表
133     SLL L;
134     cout << "請輸入五個節點的數據" << endl;
135     New_LinkList(&L, 5);
136     Print_LinkList(&L, (char*)"初始化鏈表:");
137 
138     int s, v;
139 
140     // 插入數據
141     cout << "請輸入數據插入的位置和值:";
142     cin >> s >> v;
143     Isert_LinkList(&L, s, &v);
144     Print_LinkList(&L, (char*)"插入后的節點數:");
145 
146 
147     // 查詢數據
148     cout << "請輸入數據查詢的位置:";
149     cin >> s;
150     GetElem_LinkList(&L, s, &v);
151     cout << "" << s << "個數據是:" << v << endl;
152 
153     // 刪除出數據
154     cout << "請輸入數據刪除的位置:";
155     cin >> s;
156     if (Delete_LinkList(&L, s, &v))
157     {
158         cout << "數據刪除成功,你所刪除的數據是:" << v << endl;
159     }
160     else
161     {
162         cout << "數據刪除失敗!" << endl;
163     }
164     Print_LinkList(&L, (char*)"刪除后的鏈表:");
165 
166 
167     return 0;
168 }

 尾插法

從一個空表L開始,將新結點逐個插入到鏈表的尾部,尾指針r指向鏈表的尾結點。
初始時,r同L均指向頭結點。每讀入一個數據元素則申請一個新結點,將新結點插入到尾結點后,r指向新結點。

 

  1 #include <iostream>
  2 using namespace std;
  3 
  4 #define ERROR   0
  5 #define OK      1
  6 
  7 
  8 // 鏈表節點的結構體
  9 typedef struct LNode
 10 {
 11     int data;            // 數據域
 12     struct LNode* next;    // 指針域
 13 }SLL , * SLNode;
 14 
 15 
 16 // 新建鏈表,確認鏈表的長度
 17 void New_LinkList(SLNode L, int n)
 18 {
 19     int i;
 20     int v;
 21 
 22     SLNode p,r;        // 新建單鏈表
 23     L->next = NULL;
 24     r = L;          //尾指針r指向頭節點
 25 
 26     //鏈表的尾插法
 27     for (int i = n; i > 0; i--)
 28     {
 29         p = (SLNode)malloc(sizeof(SLL));  //生成新結點
 30         cin >> v;
 31         p->data = v;                  //輸入元素值
 32         p->next = NULL; r->next = p;  //插入到表尾
 33         r = p;                        //r指向新的尾結點
 34         //插入的結點p是尾結點,所以要使r指向p,才能讓再次插入的
 35         //結點順利執行第31行。
 36     }
 37 }
 38 
 39 
 40 // 獲取鏈表中指定位置的數據元素
 41 int GetElem_LinkList(SLNode L, int i, int *e)
 42 {
 43     SLNode p;
 44     p = L->next;
 45     int j = 1;
 46 
 47     while (p && j < i)
 48     {
 49         p = p->next;
 50         ++j;
 51     }
 52 
 53     if (!p || j > i)
 54     {
 55         return ERROR;
 56     }
 57 
 58     *e = p->data;
 59     return OK;
 60 }
 61 
 62 
 63 // 在鏈表中指定位置插入數據
 64 int Isert_LinkList(SLNode L, int i, int* e)
 65 {
 66     SLNode p, s;
 67     p = L;
 68     int j = 0;
 69 
 70     while (p && j < i - 1)
 71     {
 72         p = p->next;
 73         ++j;
 74     }
 75 
 76     if (!p || j > i - 1)
 77     {
 78         return ERROR;
 79     }
 80 
 81     s = (SLNode)malloc(sizeof(SLL));
 82     s->data = *e;
 83     s->next = p->next;
 84     p->next = s;
 85 
 86     return OK;
 87 }
 88 
 89 
 90 // 刪除鏈表中制定數據元素
 91 int Delete_LinkList(SLNode L, int i, int* e)
 92 {
 93     SLNode p, q;
 94     p = L;
 95     int j = 0;
 96 
 97     while (p->next && j < i - 1)
 98     {
 99         p = p->next;
100         ++j;
101     }
102 
103     if (!(p->next) || j > i - 1)
104     {
105         return ERROR;
106     }
107 
108 
109     q = p->next;
110     p->next = q->next;
111     *e = q->data;
112 
113     free(q);
114     return OK;
115 }
116 
117 
118 // 顯示鏈表元素的內容
119 int Print_LinkList(SLNode L, char* s)
120 {
121     SLNode p;
122 
123     p = L->next;
124     if (p == NULL)
125     {
126         cout << "該鏈表為空!" << endl;
127         return ERROR;
128     }
129 
130     while (p != NULL)
131     {
132         cout << p->data << " ";
133         p = p->next;
134     }
135     cout << endl;
136     return OK;
137 }
138 
139 
140 int main()
141 {
142     // 創建並初始化鏈表
143     struct LNode L;
144     cout << "請輸入五個節點的數據" << endl;
145     New_LinkList(&L, 5);
146     Print_LinkList(&L, (char*)"初始化鏈表:");
147 
148     int s, v;
149 
150     // 插入數據
151     cout << "請輸入數據插入的位置和值:";
152     cin >> s >> v;
153     Isert_LinkList(&L, s, &v);
154     Print_LinkList(&L, (char*)"插入后的節點數:");
155 
156 
157     // 查詢數據
158     cout << "請輸入數據查詢的位置:";
159     cin >> s;
160     GetElem_LinkList(&L, s, &v);
161     cout << "" << s << "個數據是:" << v << endl;
162 
163     // 刪除出數據
164     cout << "請輸入數據刪除的位置:";
165     cin >> s;
166     if (Delete_LinkList(&L, s, &v))
167     {
168         cout << "數據刪除成功,你所刪除的數據是:" << v << endl;
169     }
170     else
171     {
172         cout << "數據刪除失敗!" << endl;
173     }
174     Print_LinkList(&L, (char*)"刪除后的鏈表:");
175 
176 
177     return 0;
178 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM