您的位置:首页 > 其它

单链表操作,创建,遍历,插入,删除,排序等操作

2015-03-01 21:02 555 查看
<pre name="code" class="cpp">#include <stdio.h>
#include <malloc.h>
#include <stdlib.h> 
#include <stdbool.h>
/*
typedef enum c_bool{ 
      false = 0,
	  true = 1,
}bool;*/ //由于c当中没有布尔类型,只能够通过枚举来定义了or通过头文件<stdbool.h>也可以 
typedef struct Node{
	int data;
	struct Node * pNext;
}NODE, *PNODE;    //NODE相当于 struct Node 和 PNODE相当于struct Node * 类型 
PNODE create_list();
void  traverse_list(PNODE pHead);
bool  is_empty(PNODE pHead);
bool  insert_list(PNODE pHead,int pos,int val); //pos从1开始 
int   length_list(PNODE pHead); 
bool  delete_list(PNODE pHead,int pos,int * pVal);
void  sort_list(PNODE pHead);
int main(void){
	PNODE pHead = NULL;
    int pos;  //要插入的位置 
    int v;
	pHead = create_list();
    traverse_list(pHead);
	printf("请输入要插入的位置:");
	scanf("%d",&pos);
	printf("请输入要插入的数字:");
	scanf("%d",&v); 
	insert_list(pHead,pos,v);
	traverse_list(pHead); 
	printf("插入后数组的长度为:%d\n",length_list(pHead));
    printf("请输入要删除的位置:");
	scanf("%d",&pos);
	if(delete_list(pHead,pos,&v)){
		printf("您删除的元素是:%d\n",v);
	} 
	else{ 
	   printf("删除失败!\n");
	} 
	traverse_list(pHead); 
	sort_list(pHead);
	printf("逆序排列后\n");
	traverse_list(pHead); 
	return 0;    
}
PNODE create_list(){
	int len;         //链表长度 
	int val;        //具体的数值 
	int i;          //循环用到的变量 
	PNODE pNew;     //新插入的节点 
	PNODE pTail;    //尾节点 
	
	printf("请输入要创建链表的长度:");
	scanf("%d",&len);
	PNODE pHead = (PNODE)malloc(sizeof(NODE)*len);
	if (pHead==NULL) {
		printf("内存分配失败\n");
		exit(-1);
	}
	pTail = pHead;
	pTail->pNext = NULL;  
	for (i=0;i<len;i++)
	{
		printf("输入第%d个数为:",i+1);
        scanf("%d",&val);
        PNODE pNew = (PNODE)malloc(sizeof(NODE));
        if (pNew == NULL){
        	printf("内存分配失败\n");
		    exit(-1);	
        }
        pNew->data = val;
        pTail->pNext = pNew;
		pNew->pNext = NULL;
        pTail = pNew;     //这里是通过这样一种思想,考虑有一个尾节点存在,然后新结构体指针 
		//始终挂在尾节点的后面,然后把新结构体指针清零,让尾节点指向新的结构体指针,这样就
		// 能够保证尾节点始终指向最后了,循环几次就是依次在尾节点上添加了 
        
        
	    /*这样是添加不进去的  这样就要为每个节点分配不同指针变量了 
        pHead->data = val;     
	    pHead->pNext = pHead;*/
	}
	
	/*应该用循环来解决问题的 
    printf("输入第2个数为:"); 
	scanf("%d",&val);
	pHead->data = val;*/
	return pHead;
}
void traverse_list(PNODE pHead){
	int i;
	int cnt;
    PNODE p = pHead; 	              //下面可以直接用p变量来代替一长串指针 ,p是指向当前元素 
				                      //也可以p=pHead->pNext 
	printf("请输入要显示几个数字:"); 
    scanf("%d",&cnt);                 
	for(i=0;i<cnt;i++){
		printf("%d",p->pNext->data);
		p = p->pNext;
		printf("\t");    	
	} 
	printf("\n");
	return;
}

bool is_empty(PNODE pHead)
{
	if (NULL == pHead->pNext)
		return true;
	else
		return false;
}
bool insert_list(PNODE pHead,int pos,int val){
	int i=0;
	PNODE p = pHead;          //这里如果改成p=pHead 下面我就不知道该怎么改了,不懂?以后调试再看看吧 
	while (NULL!=p && i<pos-1)//把头指针向后移动pos-1个,或者到空 
	{
		p = p->pNext;
		++i;
	}  //循环之后p就指向了第pos-1个,也就是pos之前的那个元素了 

	if (i>pos-1 || NULL==p)  //这小段我不知道干嘛用,不是前面都循环判断了么,为了防止意外? 
		return false;
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	pNew->data = val;
    pNew->pNext = p->pNext;
	p->pNext = pNew;
/*   这是另一种方法,和上面那种是等效的 
	PNODE q = p->pNext;
	p->pNext = pNew;
	pNew->pNext = q;*/
	return true;
	
} 
int length_list(PNODE pHead){
	PNODE p = pHead->pNext;
	int length = 0;
	while(p != NULL){
		length++;
		p = p->pNext;
	} 
	return length;
}
bool delete_list(PNODE pHead,int pos,int *pVal){
	int i = 0;
	PNODE p = pHead;  //这里为什么不能写成p= pHead->next ?因为这样就直接指向下一个元素了,要始终保持P指向要删除的前一个元素? 
    while(p!=NULL && i<pos-1){
    	p = p->pNext;
    	i++;
    }
	if (i>pos-1 || p==NULL)
	return false;
	PNODE q = p->pNext;
	*pVal = q->data;      //指针指向被删除元素的数值 
	p->pNext = q->pNext;
	free(q);              //释放掉被删除的节点 
	q = NULL; 
	//p->pNext = q->pNext; 直接写成这样内存容易溢出,被删除的那个值依然占着内存 
    return true;
}
//排序部分和普通的数组排序基本可以套用进去的,广义的算法是一样的 
void  sort_list(PNODE pHead){
	PNODE p,q;
	int len = length_list(pHead);
	int i, j, t;
	for(i=0,p=pHead->pNext; i<len-1; i++,p=p->pNext){
		for(j=i+1,q=p->pNext;j<len;j++,q=q->pNext){
			if(p->data < q->data){
				t = p->data;
				p->data = q->data;
				q->data = t;
			}
		}
	}
	return;
}






总结:

1.学会如何单链表的基本操作

2.在编译调试中遇到很多问题,学会分析并且解决问题

3.理解链路头指针存在的好处,对于临时变量p的应用在删除和插入中有点不太理解,其他地方都可以灵活运用指向下一个还是直接指向头指针,在后面调试当中慢慢再琢磨吧,那个循环判断也不是很理解pos-1的指向,为什么这样编写,不懂?

以上基本上是本次学习链表的收获,学习数据结构的第一个程序,花了近6个小时,也体会到了编程之美,之前自己都没有好好静下心来编写代码,看懂,听懂和自己编写成功运行是完全两个概念所以必须要动手,调试,运行。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐