线性表-----单链表

来源:互联网 发布:送货单打印软件 编辑:程序博客网 时间:2024/06/05 02:03

本来简单的代码,调试用来好长时间;

先定义了结构体


//线性表的链式表现及实现 //节点由数据域和指针域组成 typedef struct  LNode{ElemType data;  struct LNode *next;  //指向结构体的指针}LinkList;

下来写了个单链表初始化的函数,结果出现了 隐形的错误

void Init_List(LinkList* L)  ///^{L = (LinkList*) malloc (sizeof(LinkList)); //产生一个头结点,并使 L 指向这个头结点 if(!L)exit(-1);L->next = NULL; // 指针域为空 L->data = 0; } 

为了检验这个函数的正确性,我写了个简单的mian函数,

int main() { LinkList L1; Init_List(&L1); printf("%d\n",L1.next); return 0; }

运行结果竟然为27,这显然是编译器的随机产生的数字。其实这个错误到了最后写遍历函数才发现的,最后确定问题出在初始化函数上,显然L->next = NULL; 这条语句并没有起到作用,是什么原因呢??最终想到两个方案

(1)用return 改写函数的到如下:

LinkList* Init1_List(){LinkList* L = (LinkList*)malloc(sizeof(LinkList));if(!L)exit(-1);L->next = NULL;L->data = 0;return L;}

这样,经过返回值,就把L->next的值赋值为NULL,同时也把头指针的的数据域赋值为0,在这里,我想用这个的头指针数据域来存储单链表的长度,于是赋值为0;

(2)不用malloc函数给L->next分配空间。

void Init_List(LinkList* L)  ///^{//L = (LinkList*) malloc (sizeof(LinkList)); //产生一个头结点,并使 L 指向这个头结点 //if(!L)//exit(-1);L->next = NULL; // 指针域为空 L->data = 0; } 

如上,这样也是行的,从这个改写的结果来看,其实已经知道,在main函数中定义一个结构体变量,就已经给这个L1分配空间了,所就没有必要再分配,但是中间也有些疑惑,为什么,我传的是地址,即使分配了空间,用malloc再重新给L1赋值,应该也可以呀,为什么就不行呢???这个问题现在还没有解决。希望自己学习的深入,慢慢体会吧,同时也希望懂得人知道的话,帮我指点一二,

接下来就是几个简单的函数,分别贴出来吧:

先是两个容易弄糊涂的函数

(1)销毁线性表

void Destroy_List(LinkList* L){LinkList* q;while(!L){q = L->next;free(L);L = q;}}

(2)清空线性表

int Clear_List(LinkList *L){LinkList *p,*q;p = L->next;while(p){q = p;free(p);p = q;}L->next = NULL;}
说明:销毁单链表,包括头结点全部销毁。清空一个单链表,只把头结点以后的链表销毁,最后把头结点指针域赋值为NULL
(3)获取给定位置的元素

      1.声明一个节点 p 指向链表的第一个节点,初始化 j 从1开始 
      2.当 j < pos 时,遍历链表,让 p 的指针向后移动,不断指向下一个节点,同时 j 累加1 
      3.若链表末尾 p 为空,则说明第 pos 个元素不存在 
      4. 否则,查找成功,返回节点 p 的数据。 

int Get_List(LinkList *L,int pos ,ElemType *e){LinkList *p;p = L->next;int j = 1;while( p && j < pos){p = p->next;++j;}if( !p || j > pos)return -1;else*e = p->data;return 1;}

(3)给定位置插入一个元素

前几步和获取一个元素是一样的,只是找到这个位置后需要创建一个空间
1. 若查找成功,在系统内生成一个空的节点 s 。
2.将元素 e 赋值给 s->data  ;
3. 单链表的插入语句  s->next = p->next; p->next = s;
4.返回成功 

int List_Insert(LinkList *L,int pos, ElemType e){LinkList *p ,*s;//p = L->next;p = L;    //这点和 Get_List()是有区别的 int j =1;while( p && j<pos)  //如果 j=0; 这里的条件就变成 j < pos -1; {p = p->next;++j;}if( !p || pos > j)  //合法性判断 return -1;elses = (LinkList*)malloc(sizeof(LinkList));s->data = e;s->next = p->next;p->next = s;++(L->data);return 1;}

(4)给定位置删除元素

int List_Delete(LinkList *L,int pos, ElemType *e){int j = 0;LinkList *p,*q;p = L;while( p->next && j<pos-1){p = p->next;++j;}if( !p->next || j >pos-1)return 0;q = p->next;  //删除并释放的节点 p->next = q->next;//p 现在只想下下个元素的地址 *e = q->data;free(q);return 1;}

(5)最后一个就是写的一个遍历输出的函数(两种方法实现)

void List_Traver(LinkList *L){LinkList* p = L->next;int i = 0;/*for(i ; i<L->data;++i){printf("%d\n",p->data);p = p->next;}*/while(p){printf("%d\n",p->data);p = p->next;}}

(6)下来就到main函数了

int main(int argc, char *argv[]) {LinkList *L1 = Init1_List();int e=0;List_Insert(L1,1,1);List_Insert(L1,2,2);List_Insert(L1,2,3);List_Traver(L1);Get_List(L1,2,&e);printf("获得第二个元素%d\n",e);List_Delete(L1,2,&e);printf("删除第二个元素为:%d\n",e);List_Traver(L1);Destroy_List(L1);return 0;}

总结:线性表还是比较简单的,但是有一些问题还得自己慢慢去摸索,比如结构体成员指针的初始化等等问题










0 0
原创粉丝点击