數據結構之單向鏈表02
今天的訓練題目是,帶頭單向鏈表的操作
1.帶頭單向鏈表建立
2.帶頭單向鏈表節點添加
3.帶頭單向鏈表節點刪除
4.帶頭單向鏈表數據排序
5.兩個帶頭遞減單向鏈表合併成一個鏈表
6.帶頭/不帶頭單向鏈表的倒序
=================================================================
單鏈表操作
NOTE:包括插入,刪除,排序,倒序等
=================================================================
1.單項鍊表建立:
typedef struct Node_t {
int data;
struct Node_t *next;
}NODE_T;
/* 帶頭的單項鍊表 */
NODE_T *Init_list(int len)
{
NODE_T *head;
NODE_T *p1, p2;
int err = 0;
int n;
head = (NODE_T *)malloc(sizeof(struct Node_t));
if (!head) {
fprintf(stderr, "Create link list head failed\n");
return NULL;
}
p1 = head;
while (len--) {
p2 = (struct Node_t *)malloc(sizeof(struct Node_t));
if (!p2) {
err++;
break;
}
p1->next = p2;
p1 = p1->next;
}
p1->next = NULL;
/* free memory if malloc failed */
while (err--) {
p1 = head;
n = err;
while (n--) {
p2 = p1->next;
p1 = p2;
}
free(p1);
p1 = NULL;
}
return head;
}
==========================================================
獲取第i個元素,單向鏈表不支持隨機讀取,必須從頭指針開始遍歷
==========================================================
/**
* @brief get_link_list
*
* @param link
* @param i 1 <= i <= 表長,if i == 0,return list head
*
* @return
*/
NODE_T *get_link_list(NODE_T *link, int i)
{
NODE_T *head, p;
if (!link)
return NULL;
head = link;
while (i-- && head != NULL) {
p = head->next;
head = p;
}
return head;
}
============================================================
在第cursor節點之前插入節點,data域爲value, 插入位置大於1,
必須在頭指針以後, 0節點是頭頭節點
============================================================
/**
* @brief insert_linklist
*
* @param link
* @param cursor 1 <= cursor <= 表長
* @param value
*
* @return
*/
int insert_linklist(NODE_T *link, int cursor, int value)
{
NODE_T *head, *p;
int i;
if (!link)
return -1;
head = link;
i = 0;
while (head != NULL && i < cursor-1) {
head = head->next;
i++;
}
p = (NODE_T * )malloc(NODE_T);
if (p == NULL)
return -1;
p->next = head->next
p->data = value;
head->next = p;
return 0;
}
=======================================================
刪除節點操作,不允許刪除鏈表頭,需要先找到刪除節點的前驅節點
比如刪除第二個節點,需先找到第一個節點(節點計數從非頭節點開始)
=======================================================
int delete_linklist(NODE_T *head, int cursor)
{
NODE_T *p, p1;
int i = 0;
if (!head)
return -1;
p = head;
while (p->next != NULL && i < cursor-1) {
p = p->next;
i++;
}
if (p->next == NULL) /* the end */
fprintf(stderr, "No this position\n");
else {
p1 = p->next;
p->next = p->next->next;
free(p1);
}
return 0;
}
========================================================
帶頭單向鏈表的排序
使用冒泡法,遞減排序
========================================================
#define SWAP(a,b) {a = a + b; \
b = a - b; \
a = a - b;}
int sort_list(NODE_T *head)
{
NODE_T *p1, p2;
int n, len = 0;
if (!head)
return -1;
/* calc list length */
p1 = head->next;
while (p1 != NULL) {
len++;
p1 = p1->next;
}
while (len--) {
p1 = head->next;
/* no compare list head, compare count = len(no head) - 1 */
n = len - 1;
while (p1 != NULL && n--) {
p2 = p1->next;
if (p1->data <= p2->data)
SWAP(p1->data, p2->data);
p1 = p2;
}
}
return 0;
}
==========================================================
兩個帶頭的遞減鏈表,合併成一個遞減的鏈表
==========================================================
NODE_T *merge_linklist(NODE_T *la, NODE_T *lb)
{
NODE_T *pa, *pb, *pc;
if (!la || !lc)
return NULL;
lc = la; /* 以la節點頭作爲合併後節點頭 */
pa = la->next;
pb = lb->next;
pc = lc;
while (pa != NULL && pb != NULL) {
if (pa->data >= pb->data) {
pc->next = pa;
pc = pa;
pa = pa->next;
}
else {
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
/* 連接pa或pb中剩餘的節點 */
if (pa != NULL)
pc->next = pa;
else
pc->next = pb;
return lc;
}
=============================================================
單項鍊表的倒序
=============================================================
基本思路有兩種
1.遍歷整個鏈表,將數據提取出來,然後在逆向賦值給鏈表各節點
這需要至少遍歷兩次鏈表,並且用於存儲數據的數組,需要提前申請(沒遍歷
之前鏈表節點數量位置,則該數組大小不確定,是否應足夠大),並且只是
數據倒序了,鏈表結構並沒有倒序
2.逆向操作鏈表,即把第一個節點,作爲最後一個,並依次倒置
下面描述第二種,區別帶頭節點和不帶節點
帶頭單向鏈表的倒序
---------------------
不帶頭單向鏈表倒序
---------------------
NODE_T *reverse_link(NODE_T *head)
{
NODE_T *pn, *pt;
NODE_T *pr = NULL;
if (!head)
return NULL;
pn = head; /* no list head */
while (pn != NULL) {
pt = pn->next;
pn->next = pr;
pr = pn;
pn = pt;
}
return pr;
}
帶頭單向鏈表倒序, 頭節點不變
---------------------------------
NODE_T *reverse_link(NODE_T *head)
{
NODE_T *pn, *pt, ph;
NODE_T *pr = NULL;
if (!head)
return NULL;
ph = head;
pn = head->next;
while (pn != NULL) {
pt = pn->next;
pn->next = pr;
pr = pn;
pn = pt;
}
ph->next = pr;
return ph;
}
1.帶頭單向鏈表建立
2.帶頭單向鏈表節點添加
3.帶頭單向鏈表節點刪除
4.帶頭單向鏈表數據排序
5.兩個帶頭遞減單向鏈表合併成一個鏈表
6.帶頭/不帶頭單向鏈表的倒序
=================================================================
單鏈表操作
NOTE:包括插入,刪除,排序,倒序等
=================================================================
1.單項鍊表建立:
typedef struct Node_t {
int data;
struct Node_t *next;
}NODE_T;
/* 帶頭的單項鍊表 */
NODE_T *Init_list(int len)
{
NODE_T *head;
NODE_T *p1, p2;
int err = 0;
int n;
head = (NODE_T *)malloc(sizeof(struct Node_t));
if (!head) {
fprintf(stderr, "Create link list head failed\n");
return NULL;
}
p1 = head;
while (len--) {
p2 = (struct Node_t *)malloc(sizeof(struct Node_t));
if (!p2) {
err++;
break;
}
p1->next = p2;
p1 = p1->next;
}
p1->next = NULL;
/* free memory if malloc failed */
while (err--) {
p1 = head;
n = err;
while (n--) {
p2 = p1->next;
p1 = p2;
}
free(p1);
p1 = NULL;
}
return head;
}
==========================================================
獲取第i個元素,單向鏈表不支持隨機讀取,必須從頭指針開始遍歷
==========================================================
/**
* @brief get_link_list
*
* @param link
* @param i 1 <= i <= 表長,if i == 0,return list head
*
* @return
*/
NODE_T *get_link_list(NODE_T *link, int i)
{
NODE_T *head, p;
if (!link)
return NULL;
head = link;
while (i-- && head != NULL) {
p = head->next;
head = p;
}
return head;
}
============================================================
在第cursor節點之前插入節點,data域爲value, 插入位置大於1,
必須在頭指針以後, 0節點是頭頭節點
============================================================
/**
* @brief insert_linklist
*
* @param link
* @param cursor 1 <= cursor <= 表長
* @param value
*
* @return
*/
int insert_linklist(NODE_T *link, int cursor, int value)
{
NODE_T *head, *p;
int i;
if (!link)
return -1;
head = link;
i = 0;
while (head != NULL && i < cursor-1) {
head = head->next;
i++;
}
p = (NODE_T * )malloc(NODE_T);
if (p == NULL)
return -1;
p->next = head->next
p->data = value;
head->next = p;
return 0;
}
=======================================================
刪除節點操作,不允許刪除鏈表頭,需要先找到刪除節點的前驅節點
比如刪除第二個節點,需先找到第一個節點(節點計數從非頭節點開始)
=======================================================
int delete_linklist(NODE_T *head, int cursor)
{
NODE_T *p, p1;
int i = 0;
if (!head)
return -1;
p = head;
while (p->next != NULL && i < cursor-1) {
p = p->next;
i++;
}
if (p->next == NULL) /* the end */
fprintf(stderr, "No this position\n");
else {
p1 = p->next;
p->next = p->next->next;
free(p1);
}
return 0;
}
========================================================
帶頭單向鏈表的排序
使用冒泡法,遞減排序
========================================================
#define SWAP(a,b) {a = a + b; \
b = a - b; \
a = a - b;}
int sort_list(NODE_T *head)
{
NODE_T *p1, p2;
int n, len = 0;
if (!head)
return -1;
/* calc list length */
p1 = head->next;
while (p1 != NULL) {
len++;
p1 = p1->next;
}
while (len--) {
p1 = head->next;
/* no compare list head, compare count = len(no head) - 1 */
n = len - 1;
while (p1 != NULL && n--) {
p2 = p1->next;
if (p1->data <= p2->data)
SWAP(p1->data, p2->data);
p1 = p2;
}
}
return 0;
}
==========================================================
兩個帶頭的遞減鏈表,合併成一個遞減的鏈表
==========================================================
NODE_T *merge_linklist(NODE_T *la, NODE_T *lb)
{
NODE_T *pa, *pb, *pc;
if (!la || !lc)
return NULL;
lc = la; /* 以la節點頭作爲合併後節點頭 */
pa = la->next;
pb = lb->next;
pc = lc;
while (pa != NULL && pb != NULL) {
if (pa->data >= pb->data) {
pc->next = pa;
pc = pa;
pa = pa->next;
}
else {
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
/* 連接pa或pb中剩餘的節點 */
if (pa != NULL)
pc->next = pa;
else
pc->next = pb;
return lc;
}
=============================================================
單項鍊表的倒序
=============================================================
基本思路有兩種
1.遍歷整個鏈表,將數據提取出來,然後在逆向賦值給鏈表各節點
這需要至少遍歷兩次鏈表,並且用於存儲數據的數組,需要提前申請(沒遍歷
之前鏈表節點數量位置,則該數組大小不確定,是否應足夠大),並且只是
數據倒序了,鏈表結構並沒有倒序
2.逆向操作鏈表,即把第一個節點,作爲最後一個,並依次倒置
下面描述第二種,區別帶頭節點和不帶節點
帶頭單向鏈表的倒序
---------------------
不帶頭單向鏈表倒序
---------------------
NODE_T *reverse_link(NODE_T *head)
{
NODE_T *pn, *pt;
NODE_T *pr = NULL;
if (!head)
return NULL;
pn = head; /* no list head */
while (pn != NULL) {
pt = pn->next;
pn->next = pr;
pr = pn;
pn = pt;
}
return pr;
}
帶頭單向鏈表倒序, 頭節點不變
---------------------------------
NODE_T *reverse_link(NODE_T *head)
{
NODE_T *pn, *pt, ph;
NODE_T *pr = NULL;
if (!head)
return NULL;
ph = head;
pn = head->next;
while (pn != NULL) {
pt = pn->next;
pn->next = pr;
pr = pn;
pn = pt;
}
ph->next = pr;
return ph;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.