数据结构笔记一(20120818)
1.顺序表
逻辑(数值)上相邻,地址上连续,是顺序结构。
添加节点和删除节点,结果就是后面所有的数进行前移或往后移动;
2.链表
链表的创建,增加,排序和删除节点;
单链表:逻辑(数值)上相邻,地址上不一定连续;
用结构体来表示,一个数据和其地址,为一个节点;
typedef struct node
{
struct stu s;
struct node *next; //可以不断的指向链表中的下一个数据地址;
}NODE;
创建链表:
定义指针后,先进行初始化,将指针赋值NULL或者有效的值,应用的时候,需要进行对指针进行判断。
在创建链表的函数creatlist()可以修改head的值,只有将地址传过去;或者不传参数,只将返回值返回到head;
一般查找用顺序表,插入和删除用链表,在这两种情况下效率高;
如果用定义的变量或对象的方式进行分配空间,结果是分配空间到堆,用malloc就是在堆区,需要进行free的释放。
**********************************代码及其分析**********************************
/*
*wuxiuwen
*链表的创建,增加、删除节点
*
*/
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *next;
}NODE;
//函数的声明
void Creatlist(NODE **);
void output(NODE const *);
void freelist(NODE **);
NODE *getnode();
NODE *insertlist(NODE *head,int pos);
NODE *insertlist_node(NODE *head,NODE *pnew);
NODE *removenode(NODE *head,NODE *pnew);
//函数的声明的结束
int main()
{
NODE *head = NULL;
int m;
NODE *pnew=NULL;
Creatlist(&head);
/*创建链表,链表的头部是head,因为要对链表操作,所以取其地址进行操作*/
output(head);
//输出链表
head = insertlist(head,5); //插入到链表中的第五个位置
output(head);
pnew = getnode(); //获取一个节点,用来进行增加和删除操作
head = insertlist_node(head,pnew);//插入节点pnew到有序的链表中,形成有序的链表
output(head);
head = removenode(head,pnew); //删除head链表中的与pnew有匹配的节点
output(head);
freelist(&head); //释放空间
}
/*释放申请链表时用malloc申请的堆的空间
*/
void freelist(NODE **phead)
/*可以对当前的链表进行操作,传递的进来的是指向头链表的指针*/
{
NODE *pp=NULL;
while(*phead !=NULL) //用循环,释放每一个申请的堆的空间
{
pp=*phead;
*phead = (*phead)->next; //这两句就是遍历了整个链表
free(pp);
}
}
NODE *insertlist(NODE *head,int pos) //插入到链表中的第POS个位置
{
NODE *pnew=getnode(); //获取到一个节点,将这个节点插入到head中的第POS个
/*思路是思考几种情况,如果是空链表,如果不是空链表的话,插入到第一个位置,或 者是插入到不是第一个位置*/
NODE *p=NULL;
int i;
if(head ==NULL)
{
head=pnew;
return head;
}
if(pos ==1)
{
p->next = head;
head=p;
return head;
}
i = pos -2;
p = head;
while(i !=0 && p->next !=NULL) //这个循环用来定位到第POS前的以为的NODE
//如果这个位置超出这个链表的长度,直接放到最后
{
p = p->next; //p =head,从开始头出开始遍历
--i;
}
pnew ->next = p->next;
//将这个心的节点插入到第POS的位置上,因为当前的p->next就是要插入的位置*/
p->next = pnew;
return head; //返回修改后的链表的头
}
void output(NODE const *phead) //输入链表,主要是用来打印,做验证用
{
NODE *pp =NULL;
pp = (NODE *)phead;
/*强制类型转换,传递进来的是一个const的值,不会修改到原来的链表的任何的值;*/
while(pp!=NULL)
{
printf("%d\t",pp->data); //遍历输出
pp = pp->next;
}
printf("\n");
}
NODE *getnode() /*利用动态分配空间来进行获取节点*/
{
NODE *pnew;
pnew =(NODE *)malloc(sizeof(NODE));
if(pnew == NULL)
{
exit(1);
}
scanf("%d",&(pnew->data));
pnew->next=NULL;
return pnew;
}
void Creatlist(NODE **phead) /* 创建链表, */
/*可以对当前的链表进行操作,传递的进来的是指向头链表的指针*/
{
NODE *pnew=NULL;
NODE *pend =NULL;
pnew =getnode();
while(pnew->data!=0)
{
if(*phead == NULL) //初始化链表的第一个节点
{
*phead = pnew;
pend = pnew;
}
else
{
pend->next = pnew; //进行从第二个节点的定位和赋值
pend = pnew;
// pnew->next = *phead;
// *phead = pnew;
}
pnew = getnode(); //对下面的节点进行获取
}
free(pnew); //释放最后一个分配的空间
}
NODE *insertlist_node(NODE *head,NODE *pnew)
/*插入节点pnew到有序的链表中,形成有序的链表*/
{
int i;
NODE *p = head;
if(p == NULL)
{
head = pnew;
return head;
}
if((p == head) && (p->data) >= (pnew->data)) //程序的健壮性(p == head)
{
pnew->next = head; //插入到第一个节点上
head = pnew;
return head;
}
/*根据DATA数值的判断,定位到p->next的值为要插入的值,然后进行节点的插入*/
while(p->next != NULL)
{
if((p->data) < (pnew->data) && (p->next->data) >= (pnew->data))
{
break;
}
p = p->next;
}
pnew ->next = p->next;
/*根据DATA数值的判断,定位到p->next的值为要插入的值,然后进行节点的插入*/
p->next = pnew;
return head;
}
NODE *removenode(NODE *head,NODE *pnew)
{
NODE *pp=NULL;
pp =head;
if(head == pnew)
{
head =head->next;
return head;
}
while(pp->next !=NULL)
{
if(pp->next !=pnew)
{
pp= pp->next;
}
else
{
pp->next = pp->next->next;
free(pp->next);
return head;
}
if(pp->next ==NULL)
{
printf("here is error,please input other node!\n");
}
}
}
*********************************执行结果****************************
[root@localhost 20120818]# ./a.out
2 4 6 7 0
2 4 6 7
8
2 4 6 7 8
5
2 4 5 6 7 8
2 4 0 7 8
[root@localhost 20120818]#