在了解线性结构后我们知道它可分为顺序表和链表两种,而顺序表又分为静态顺序表和动态顺序表.
静态顺序表和静态通讯录的实现极为相似,但是我们知道静态版本有着明显的缺陷,空间分配太大易造成浪费,太小又不便存储,而动态版本正好可以解决这个问题。
既然前面提到线性结构的组成,那么我们就在说说链表分为哪些:它可分为单向链表,双向链表,循环链表和双向循环链表,这些我们后期再讨论这些。好了,该回到今天的主题上来了——动态顺序表的实现!
首先,动态顺序表的功能在头文件中已经全部列出来了,在排序的时候给出了三种方式:冒泡排序,直接插入排序和选择排序。在实现测试函数的时候记得打印菜单中的顺序需要和case语句中的顺序保持一致哦,我在这就栽过跟头。。。还值得注意的是:在我们的测试函数中,应当创建一个结构体变量,然后调用函数的时候把其地址传进去,否则传值的话会有压栈的开销,这样一来时间和空间就都浪费很大了。
下来我们就用代码实现它:
Seqlist.h
#define _CRT_SECURE_NO_WARNINGS 1 #ifndef _SEQLIST_D_H_ #define _SEQLIST_D_H_ #include<stdio.h> #include<stdlib.h> #include<string.h> #define DEFAULT_SZ 2 #define INC_SZ 2 typedef int DataType; typedef struct Seqlist { DataType *data; int sz; //实际容量大小 int capacity; }Seqlist,*pSeqlist; void PrintSeqlist(pSeqlist pSeq); //顺序表打印输出 void InitSeqlist(pSeqlist pSeq); //进行初始化 void DestroySeqlist(pSeqlist pSeq); void PushBack(pSeqlist pSeq,DataType x);//在顺序表尾部插入元素 void PopBack(pSeqlist pSeq); //在顺序表尾部删除元素 void PushFront(pSeqlist pSeq,DataType x);//在顺序表头部插入元素 void PopFront(pSeqlist pSeq); //在顺序表头部删除元素 void Insert(pSeqlist pSeq,int pos,DataType x);//在顺序表指定位置插入元素 void Erase(pSeqlist pSeq,DataType pos); //在指定位置删除该元素 void Remove(pSeqlist pSeq,DataType x); //删除指定元素 void RemoveAll(pSeqlist pSeq,DataType x); //删除所有指定的元素 void BubbleSort(pSeqlist pSeq); //冒泡排序 void InsertionSort(pSeqlist pSeq); //直接插入排序 void SelectSort(pSeqlist pSeq); //选择排序 int BinarySearch(pSeqlist pSeq,DataType x); //二分查找 #endif
Seqlist.c
#include"Seqlist.h" void PrintSeqlist(pSeqlist pSeq) //顺序表打印输出 { int i=0; for(i=0;i<pSeq->sz;i++) { printf("%d\n",pSeq->data[i]); } } void InitSeqlist(pSeqlist pSeq) //进行初始化 { pSeq->data=(DataType *)malloc(DEFAULT_SZ*sizeof(DataType)); if(pSeq->data==NULL) { printf("out of memory"); exit(EXIT_FAILURE); } pSeq->sz=0; pSeq->capacity=0; memset(pSeq->data,0,DEFAULT_SZ*sizeof(DataType)); } void DestroySeqlist(pSeqlist pSeq) { free(pSeq->data); pSeq->data=NULL; pSeq->capacity=0; pSeq->sz=0; } void Check_capacity(pSeqlist pSeq) { DataType *tmp=NULL; if(pSeq->sz==pSeq->capacity) { tmp=(DataType *)realloc(pSeq->data,(pSeq->capacity+=INC_SZ)*sizeof(DataType)); if(tmp==NULL) { printf("out of memmory!"); exit(EXIT_FAILURE); } pSeq->data=tmp; pSeq->capacity+=INC_SZ; } } void PushBack(pSeqlist pSeq,DataType x) //在顺序表尾部插入元素 { Check_capacity(pSeq); pSeq->data[pSeq->sz]=x; pSeq->sz++; } void PopBack(pSeqlist pSeq) //在顺序表尾部删除元素 { if(pSeq->sz==0) { printf("顺序表已空!"); return; } pSeq->sz--; } void PushFront(pSeqlist pSeq,DataType x) //在顺序表头部插入元素 { int i=0; Check_capacity(pSeq); for(i=pSeq->sz-1;i>=0;i--) { pSeq->data[i+1]=pSeq->data[i]; } pSeq->data[0]=x; pSeq->sz++; } void PopFront(pSeqlist pSeq) //在顺序表头部删除元素 { int i=0; if(pSeq->sz==0) { printf("顺序表已空!"); return; } for(i=0;i<pSeq->sz;i++) { pSeq->data[i]=pSeq->data[i+1]; } pSeq->sz--; } void Insert(pSeqlist pSeq,int pos,DataType x) //在顺序表指定位置插入元素 { int i=0; Check_capacity(pSeq); for(i=pSeq->sz-1;i>=pos;i--) { pSeq->data[i+1]=pSeq->data[i]; } pSeq->data[pos]=x; pSeq->sz++; } void Erase(pSeqlist pSeq,DataType pos) //在顺序表指定位置删除元素 { int i=0; if((pos<0)&&(pos>pSeq->sz)) { printf("删除位置不合法!"); return; } for(i=pos;i<pSeq->sz-1;i++) { pSeq->data[i]=pSeq->data[i+1]; } pSeq->sz--; } void Remove(pSeqlist pSeq,DataType x) //删除指定元素 { int i=0; int ret=0; ret=BinarySearch(pSeq,x); if(ret==-1) { printf("没有找到该元素!\n"); return; } for(i=ret;i<pSeq->sz;i++) { pSeq->data[i]=pSeq->data[i+1]; } pSeq->sz--; } void RemoveAll(pSeqlist pSeq,DataType x) //删除所有指定的元素 { int i=0; int ret=0; ret=BinarySearch(pSeq,x); while(ret<pSeq->sz) { if(ret==-1) { printf("没有找到该元素!\n"); return; } for(i=ret;i<pSeq->sz;i++) { pSeq->data[i]=pSeq->data[i+1]; } pSeq->sz--; ret++; } } void BubbleSort(pSeqlist pSeq) //冒泡排序 { int i=0; int j=0; int m=0; DataType tmp=0; int k=pSeq->sz-1; int flag=0; //表示有序 for(i=0;i<pSeq->sz-1;i++) { m=0; flag=0; for(j=0;j<k;j++) { if((pSeq->data[j])>(pSeq->data[j+1])) { tmp=pSeq->data[j]; pSeq->data[j]=pSeq->data[j+1]; pSeq->data[j+1]=tmp; flag=1; m=j; //记住最后一次交换的位置 } } if(flag==0) { return; } m=k; //将k设置为最后一次交换的位置 } } void InsertionSort(pSeqlist pSeq) //直接插入排序 { int i=0; int j=0; DataType tmp=0; for(i=1;i<pSeq->sz;i++) //控制插入的位置(假设第一个为有序) { tmp=pSeq->data[i]; for(j=i-1;(j>=0)&&(pSeq->data[j]>tmp);j--)//满足取出的值大于这个值才进入循环 { pSeq->data[j+1]=pSeq->data[j]; } pSeq->data[j+1]=tmp; } } void SelectSort(pSeqlist pSeq) //选择排序 { int i=0; int j=0; DataType tmp=0; int min=0; //作为最小值的下标 for(i=0;i<pSeq->sz;i++) { min=i; //假设第一个为有序(对升序而言第一个为最小值) for(j=i+1;j<pSeq->sz;j++) { if(pSeq->data[j]<pSeq->data[min]) { min=j; } if(min!=i) { tmp=pSeq->data[min]; pSeq->data[min]=pSeq->data[i]; pSeq->data[i]=tmp; } } } } int BinarySearch(pSeqlist pSeq,DataType x) //二分查找 { int left=0; int right=pSeq->sz-1; int mid=0; mid=(right-left)/2+left; while(left<right) { if(pSeq->data[mid]<x) { right=mid-1; } else if(pSeq->data[mid]>x) { left=mid+1; } else return mid; //返回要查找值的下标,否则要查找的可能也为-1 } return -1; }
test.c
#include "Seqlist.h" void menu() { printf("******************************************\n"); printf("***0.exit***************1.PrintSeqlist****\n"); printf("***2.InitSeqlist********3.PushBack********\n"); printf("***4.PopBack************5.PushFront*******\n"); printf("***6.PopFront**********7.Insert***********\n"); printf("***8.Remove*************9.RemoveAll*******\n"); printf("***10.BubbleSort******11.InsertionSort****\n"); printf("***12.SelectSort*****13.BinarySearch******\n"); printf("******14.DestroySeqlist***15.Erase********\n"); printf("******************************************\n"); } void test() { Seqlist Seq ; //创建一个结构体变量 DataType x=0; int ret=0; int pos=0; int input=1; pSeqlist pSeq = &Seq; InitSeqlist(&Seq); while(input) { menu(); printf("请选择:"); scanf("%d",&input); switch(input) { case 0: exit(1); break; case 1: PrintSeqlist(&Seq); break; case 2: InitSeqlist(&Seq); break; case 3: printf("请输入一个要插入的数:"); scanf("%d",&x); PushBack(&Seq,x); break; case 4: PopBack(&Seq); break; case 5: printf("请输入一个要插入的数:"); scanf("%d",&x); PushFront(&Seq,x); break; case 6: PopFront(&Seq); break; case 7: printf("请输入一个要插入的数:"); scanf("%d",&x); printf("请选择要插入的位置:"); scanf("%d",&pos); Insert(&Seq,pos,x); break; case 8: printf("请输入要删除的元素:"); scanf("%d",&x); Remove(&Seq,x); break; case 9: printf("请输入要删除的元素:"); scanf("%d",&x); RemoveAll(&Seq,x); break; case 10: BubbleSort(&Seq); break; case 11: InsertionSort(&Seq); break; case 12: SelectSort(&Seq); break; case 13: printf("请输入要查找的数:"); scanf("%d",&x); ret=BinarySearch(&Seq,x); if(ret!=-1) { if(pSeq->data[ret]==x) { printf("%d\n",x); printf("查找成功!\n"); } else printf("查找失败!\n"); } if(ret==-1) { printf("查找失败!\n"); } break; case 14: DestroySeqlist(&Seq); break; case 15: printf("请输入要删除元素的位置:"); scanf("%d",x); Erase(&Seq,x); default: printf("输入错误!"); break; } } } int main() { test(); system("pause"); return 0; }