應用C說話完成次序表的實例操作。本站提示廣大學習愛好者:(應用C說話完成次序表的實例操作)文章只能為提供參考,不一定能成為您想要的結果。以下是應用C說話完成次序表的實例操作正文
本文實例講述了C說話完成次序表(線性表)的辦法。分享給年夜家供年夜家參考,詳細以下:
一:次序表代碼完成
#ifndef _SEQ_LIST_H
#define _SEQ_LIST_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define ElemType float //以float類型測試算法通用性,而不是以習用的int
#define INIT_SIZE 10 //次序表默許初始化年夜小
#define LIST_INCREMENT 5 //次序表容量增量,容量不敷應用malloc請求
#define list_full(list) ((list)->size >= (list)->capacity ? 1 : 0) //次序表判滿
#define list_empty(list) ((list)->size == 0 ? 1 : 0) //判空
typedef ElemType value_type; //元素類型
typedef value_type* value_ptr; //元素指針類型
typedef enum {false, true}bool; //為C說話增長bool量
typedef enum {POSITION, VALUE}DELETE_MODE; //刪除元素形式選擇,分離為按地位刪除和按值刪除
typedef struct sequelize_list{
ElemType *base; //次序表基址
int size; //次序表元素年夜小
int capacity; //次序表容量
} seq_list, *list_ptr;
void init_list(list_ptr lp) //初始化
{
assert(lp != NULL);
lp->base = (value_ptr)malloc(sizeof(value_type)*INIT_SIZE); //free
assert(lp->base != NULL);
memset(lp->base, 0, sizeof(value_type)*INIT_SIZE);
lp->size = 0;
lp->capacity = INIT_SIZE;
}
bool insert_elem(list_ptr lp, const int pos, const value_type elem) //拔出元素
{
assert(lp != NULL && pos >= 1 && pos <= lp->size+1);
if(list_full(lp)){ //假如表滿,追加請求空間
value_ptr new_base = (value_ptr)realloc(lp->base,
sizeof(value_type)*(lp->capacity+LIST_INCREMENT));//此處留意realloc用法,用新地址吸收是為了避免realloc掉敗,原地址有用內容被釋放
assert(new_base != NULL); //而且realloc填寫的請求空間年夜小必需是之前的年夜小+增量的年夜小,而不是只寫增量,不然假如原地址內存不敷,在新地址請求增量年夜小的空間,將之前的內容挪至新空間,內存溢出,將產生段毛病
lp->base = new_base; //再賦回給原地址
lp->base[lp->capacity] = elem;
lp->capacity += LIST_INCREMENT;
++lp->size;
}
else{ //未滿,拔出元素
for(int i=lp->size-1; i>=pos-1; --i){ //將元素後移,騰出地位
lp->base[i+1] = lp->base[i];
}
lp->base[pos-1] = elem; //拔出元素
++lp->size;
//}
return true;
}
bool remove_elem_pos(list_ptr *lp, const int pos) //按地位刪除
{
assert(pos >= 1 && pos <= (*lp)->size);
for(value_ptr ptmp=&(*lp)->base[pos-1]; ptmp<&(*lp)->base[(*lp)->size-1]; ++ptmp)
*ptmp = *(ptmp+1);
(*lp)->base[(*lp)->size-1] = 0;
--(*lp)->size;
return true;
}
bool remove_elem_val(list_ptr *lp, value_type elem) //按值刪除
{
for(int i=0; i<(*lp)->size; ++i)
if((*lp)->base[i] == elem){
for(int j=i; j<(*lp)->size-1; ++j) //一切相符請求的值都被刪除
(*lp)->base[j] = (*lp)->base[j+1];
(*lp)->base[(*lp)->size-1] = 0;
--(*lp)->size;
}
return true;
}
bool remove_elem(list_ptr lp, const void* clue, DELETE_MODE mode) //內部接口,第三個參數選擇按地位或按值刪除形式
{
assert(lp != NULL);
if(list_empty(lp)){ //表空,不克不及刪
fprintf(stdout, "already empty, can not remove.\n");
return false;
}
if(mode == POSITION){ //參數為POSITION,按地位刪除
remove_elem_pos(&lp, *(int *)clue);
}
else{ //不然按值刪除
remove_elem_val(&lp, *(value_ptr)clue);
}
return true;
}
void print_list(const seq_list sl) //打印函數
{
if(sl.size == 0)
fprintf(stdout, "nil list.");
for(int i=0; i<sl.size; ++i)
printf("%f ", sl.base[i]);
printf("\n");
}
int compare(const void *vp1, const void* vp2) //比擬函數
{
return *(value_ptr)vp1 - *(value_ptr)vp2;
}
int locate_elem(const seq_list sl, const value_type elem,
int (*compare)(const void *, const void *)) //定位函數
{
if(list_empty(&sl)){
fprintf(stdout, "list empty, con not locate.\n");
}
else{
for(int i=0; i<sl.size; ++i)
if((*compare)(&sl.base[i], &elem) == 0) //相等則找到,前往地位
return i+1;
}
return 0;
}
void sort_list(list_ptr lp, int (*compare)(const void *, const void *)) //排序函數
{
assert(lp != NULL);
qsort(lp->base, lp->size, sizeof(value_type), compare); //挪用體系疾速排序
}
void merge_list(list_ptr lpa, list_ptr lpb, list_ptr combine,
int (*compare)(const void *, const void *)) //歸並兩個次序表
{
assert(lpa != NULL && lpb != NULL && combine != NULL);
combine->base = (value_ptr)malloc(sizeof(value_type)
*(lpa->size+lpb->size)); //此處為新表請求空間,是以新表無需別的挪用初始化函數,不然會產生內存洩露
assert(combine->base != NULL);
combine->capacity = combine->size = lpa->size+lpb->size;
value_ptr it_pc = combine->base;
value_ptr it_pa=lpa->base;
value_ptr it_pb=lpb->base;
while(it_pa<lpa->base+lpa->size && it_pb<lpb->base+lpb->size){ //由小到年夜拔出新表
if(compare(it_pa, it_pb) <= 0)
*it_pc++ = *it_pa++;
else
*it_pc++ = *it_pb++;
}
while(it_pa < lpa->base+lpa->size) //從下面while出輪回只要兩種情形,此處為pa為插完,pb已插完,pa殘剩元素直接拔出,自然有序
*it_pc++ = *it_pa++;
while(it_pb < lpb->base+lpb->size) //同理,若pb剩有元素,直接拔出,自然有序
*it_pc++ = *it_pb++;
}
#endif /*seq_list*/
二:測試代碼
為包管通用性,不消int,用float測試。
#include "seq_list.h"
#define ARRAY_SIZE 10
int main()
{
value_type array[] = {39.1, 32.1, 10.1, 11.1, 22.1, 5.1, 36.1, 28.1, 46.1, 32.1};
seq_list list; //次序表1
init_list(&list);
for(int i=0; i<ARRAY_SIZE; ++i)
insert_elem(&list, 1, array[i]);
printf("list:\n");
print_list(list);
#if 1
int clue = 1; //按次序刪除,刪除第一個元素
//value_type clue = 32.1; //按值刪除,刪除值為32.1的元素,需修正上面參數為VALUE
printf("after remove:\n");
remove_elem(&list, &clue, POSITION);
print_list(list);
#endif
#if 1
int found = locate_elem(list, 22.1, compare); //定位22.1元素地點地位
if(found >= 1)
fprintf(stdout, "found %f at the position %d\n", list.base[found-1], found);
else
fprintf(stdout, "not found.\n");
#endif
sort_list(&list, compare);
printf("list after sort:\n");
print_list(list);
value_type array2[] = {98.1, 65.1, 4.1, 86.1, 34.1, 21.1, 86.1, 74.1, 93.1, 46.1};
seq_list list2;
init_list(&list2);
for(int i=0; i<ARRAY_SIZE; ++i)
insert_elem(&list2, 1, array2[i]);
printf("list2:\n");
print_list(list2);
printf("list2 after sort:\n");
sort_list(&list2, compare);
print_list(list2);
seq_list new_list; //無需挪用init函數初始化,由於新表在merge_list中會初始化。假如強行挪用,那末會湧現內存洩露。
merge_list(&list, &list2, &new_list, compare);
printf("new merge_list:\n");
print_list(new_list);
free(list.base);
free(list2.base);
free(new_list.base); //三個釋放,避免內存洩露
return 0;
}
三:測試成果
四:總結
以上就是本文的全體內容,願望對年夜家進修應用C說話能有所贊助。