您的位置:首页 > 其它

关于线性链表的一些操作

2007-03-30 14:44 429 查看
线性链表是数据结构中的第一个概念, 也是最基本的概念。如果对线性链表的操作不熟悉,就说明你对指针、算法等不甚了解,或者说对C语言的精髓、算法的初步都未入门。下文给出的一个线性表的示例,给大家演示线性表的操作,让大家熟悉对指针、链表的操作。该程序中大部分的代码都是标准操作,各种数据结构相关的教科书中都有,不过采用的不一定是C语言而已,但不是很难,所以不加任何介绍,只是在程序中给出响应的注释。不过有一段特别的代码,就是将链表倒置的代码


void List_Reverse(List L)



该函数的功能就是将线性表倒置。大家别小看这么一个操作,如果是顺序表(数组),这个操作是相当简单的,但是对于链表,可得想好了,否则,上机调试越调越乱〔其实所有的链表操作都是如此,如果事先没有想好就上机,除了浪费时间好像没有多大的意义〕。当然链表倒置操作方法不止一种,我们在此采用一个类似递归的的思想(别看见递归就头疼,你当我没说过递归)。

链表倒置,我们将链表看做两个表,LA和LB。其中LA是原表,LB是已经将LA前面的一部分已经倒置的线性表。我们操作的过程用语言描述就是一句话:将LA的第一个结点插入到LB的最前面。所以操作过程分开写就是:
1) 将LA指向当第一个结点插入到LB的第一个结点
2) 将LB指向刚插入的结点
3) LA后移动一个
这样循环操作直至LA指向空

当然实际操作中考虑到是否有头结点(程序中是使用头结点的),我们把原代码贴出来,然后逐一解释


void List_Reverse(List L)




...{


List p = L, q = L->next;




while (q != NULL) ...{


L->next = q->next;


q->next = p;


if (q->next == L)


q->next = NULL;


p = q;


q = L->next;


}


L->next = p;


}



p=L, q=L->next; 该操作是相当于q为LA,p为LB;
while(q!=NULL) 表示当LA不为空,也就是还有有效结点时继续循环
L->next = q->next; 将q的下一个结点插入到L的第一个结点(第0个为头结点)
q->next = p; 重新接好链表(否则链表就断了)
if(q->next==L) q->next = NULL; 不用看,这肯定是放在最后的,实际上也就是插入的第一个结点后要将“下一位”赋空,否则会死得很惨的。
p = q;
q = L->next; 重新赋值,也就是保证q总是在最开始,q是新表的第一个结点
我们可以看下图



下面是程序代码,以及运行结果


#include <string.h>


#include <malloc.h>




#pragma once


#define MAXINFOLEN 128






typedef struct _ElemType...{


int m_nKey; // 关键字


char m_sInfo[MAXINFOLEN]; // 消息


} ElemType;


void Elem_Print(ElemType *e);






// Houjian TANG @ 20070330


typedef struct _NodeType




...{


ElemType *elem; // 节点元素指针


struct _NodeType *next; // 下一个节点


} NodeType, *List;




typedef int (*COMPARE)(ElemType *e1, ElemType *e2);




int compare_key(ElemType *e1, ElemType *e2);


int compare_info(ElemType *e1, ElemType *e2);








// 打印一个节点


void LNode_Print(NodeType *e);


// 打印一个链表


void List_Print(List L);


// 初始化一个带头结点的链表,返回链表的头


List List_Init();


// 将元素e插入到链表L的pos位置处,如果pos<0或非常大,则插入到最后


void List_Insert(List L, int pos, ElemType *e);


// 删除链表L的pos处的节点,如果pos值非常大或者pos<0,返回失败


// 删除成功返回true,并将被删除的元素放到e指向的单元中(e!=NULL)


bool List_Delete(List L, int pos, ElemType *e);


int List_Locate(List L, COMPARE compare, ElemType *e);


List List_GetNode(List L, int pos);


bool List_Delete(List L, int pos, ElemType *e);


void List_Destroy(List L);


void List_Reverse(List L);


void List_Test();




int main()




...{


List_Test();


return 0;


}






void List_Test()




...{


List L;


ElemType e;


int i = 0;




L = List_Init();


// 建立5个节点的链表


printf("Create a link with 5 nodes: ");




for (i=0; i<5; i++) ...{


e.m_nKey = i;


sprintf(e.m_sInfo, "Elem Node %d", i);


List_Insert(L, i, &e);


}


List_Print(L);




printf("Reverse this link: ");


List_Reverse(L);


List_Print(L);




printf("Call Search(e.m_nKey==3): ");


e.m_nKey = 3;


i = List_Locate(L, compare_key, &e);




if (i >= 0) ...{


printf("founded! p = ");


LNode_Print(List_GetNode(L, i));


printf(" ");


printf("Delete this node: ");


List_Delete(L, i, &e);


List_Print(L);


}




else ...{


printf("Not founded! ");


}




printf("Call Search(e.m_sInfo=='Elem Node 4'): ");


sprintf(e.m_sInfo, "Elem Node 4");


i = List_Locate(L, compare_info, &e);




if (i >= 0) ...{


printf("founded! p = ");


LNode_Print(List_GetNode(L, i));


printf(" ");


printf("Delete this node: ");


List_Delete(L, i, &e);


List_Print(L);


}




else ...{


printf("Not founded! ");


}




e.m_nKey = 30;


sprintf(e.m_sInfo, "an other node");


printf("Insert a node = (%d, '%s') ",


e.m_nKey, e.m_sInfo);


List_Insert(L, 2, &e);


List_Print(L);




List_Destroy(L);


}






void LNode_Print(NodeType *e)




...{


printf("{%pH: || e=", e);


Elem_Print(e->elem);


printf("] next->%pH)", e->next);


}




void List_Print(List L)




...{


printf("// ------------------------------ ");




while ((L = L->next) != NULL) ...{


LNode_Print(L);


printf(" ");


}


printf("------------------------------ // ");


}




// 分配头节点


List List_Init()




...{


List L = (NodeType *)malloc(sizeof(NodeType));


L->next = NULL;


L->elem = (ElemType *)malloc(sizeof(ElemType));


// L->elem = NULL;


//L->elem->m_nKey = 0;


//L->elem->m_sInfo[0] = 0;


return L;


}




void List_Insert(List L, int pos, ElemType *e)




...{


List p = L, lTmp;


int i;




// 如果是负数,则插入到最后




if (pos < 0) ...{


while (p->next != NULL) // 该循环是将tail指向列表的末尾


p = p->next;


}


// 查找的pos个位置




for (i=0; i<pos; i++) ...{


if (p->next == NULL) // 如果已经到了末尾,就不继续了


break;


p = p->next;


}


// 先申请链表结点


lTmp = (NodeType *)malloc(sizeof(NodeType));


// 再分配链表结点的内容


lTmp->elem = (ElemType *)malloc(sizeof(ElemType));


*(lTmp->elem) = *e;




// 注意下面这两行,实现了链表的连接


lTmp->next = p->next;


p->next = lTmp;


}




bool List_Delete(List L, int pos, ElemType *e)




...{


List p = L, q = NULL;


int i = 0;


if (pos < 0)


return false;




for (i=0; i<pos; i++)...{


if (p->next->next == NULL)


return false;


p = p->next;


}




// 下面这两句是去掉q所指向的元素


q = p->next;


p->next = q->next;


if (e != NULL)


*e = *(q->elem);




// 注意一定要释放


free(q->elem);


q->next = NULL;


q->elem = NULL;


free(q);


return true;


}




void List_Destroy(List L)




...{


List p = L;




while (L != NULL) ...{


p = L;


L = L->next;


free(p->elem);


p->next = NULL;


p->elem = NULL;


free(p);


}


}




int List_Locate(List L, COMPARE compare, ElemType *e)




...{


int i = 0;


L = L->next;




while (L != NULL) ...{


if (compare(L->elem, e) == 0)


return i;


L = L->next;


i ++;


}


return -1;


}






void Elem_Print(ElemType *e)




...{


printf("{%03d: '%s'}", e->m_nKey, e->m_sInfo);


}






List List_GetNode(List L, int pos)




...{


L = L->next;




while (L != NULL) ...{


pos --;


if (pos < 0)


return L;


L = L->next;


}


return NULL;


}




void List_Reverse(List L)




...{


List p = L, q = L->next;




while (q != NULL) ...{


L->next = q->next;


q->next = p;


if (q->next == L)


q->next = NULL;


p = q;


q = L->next;


}


L->next = p;


}




int compare_key(ElemType *e1, ElemType *e2)




...{


return e1->m_nKey - e2->m_nKey;


}


int compare_info(ElemType *e1, ElemType *e2)




...{


return strcmp(e1->m_sInfo, e2->m_sInfo);


}








/**//*


运行结果:


// ------------------------------


{0x4F1EF0: elem={0: 'Elem Node 0'}, next=0x4F1E00}


{0x4F1E00: elem={1: 'Elem Node 1'}, next=0x4F1D10}


{0x4F1D10: elem={2: 'Elem Node 2'}, next=0x4F1C20}


{0x4F1C20: elem={3: 'Elem Node 3'}, next=0x4F1B30}


{0x4F1B30: elem={4: 'Elem Node 4'}, next=0x0}


------------------------------ //


// ------------------------------


{0x4F1B30: elem={4: 'Elem Node 4'}, next=0x4F1C20}


{0x4F1C20: elem={3: 'Elem Node 3'}, next=0x4F1D10}


{0x4F1D10: elem={2: 'Elem Node 2'}, next=0x4F1E00}


{0x4F1E00: elem={1: 'Elem Node 1'}, next=0x4F1EF0}


{0x4F1EF0: elem={0: 'Elem Node 0'}, next=0x0}


------------------------------ //


founded!


p = {0x4F1C20: elem={3: 'Elem Node 3'}, next=0x4F1D10}


// ------------------------------


{0x4F1B30: elem={4: 'Elem Node 4'}, next=0x4F1D10}


{0x4F1D10: elem={2: 'Elem Node 2'}, next=0x4F1E00}


{0x4F1E00: elem={1: 'Elem Node 1'}, next=0x4F1EF0}


{0x4F1EF0: elem={0: 'Elem Node 0'}, next=0x0}


------------------------------ //


--------------------------------


{0: 'ElemType 0'}


{1: 'ElemType 1'}


{2: 'ElemType 2'}


{3: 'ElemType 3'}


{4: 'ElemType 4'}


{5: 'ElemType 5'}


{6: 'ElemType 6'}


{7: 'ElemType 7'}


{8: 'ElemType 8'}


{9: 'ElemType 9'}


--------------------------------


{9: 'ElemType 9'}


{8: 'ElemType 8'}


{7: 'ElemType 7'}


{6: 'ElemType 6'}


{5: 'ElemType 5'}


{4: 'ElemType 4'}


{3: 'ElemType 3'}


{2: 'ElemType 2'}


{1: 'ElemType 1'}


{0: 'ElemType 0'}


Found! ElemType is : {6: 'ElemType 6'}






*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: